返回顶部

收藏

C#在多行字符串中查找指定信息,类似linux下的grep功能

更多
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

namespace RobvanderWoude
{
    class RxGrep
    {
        public static int skipmatches = 0;
        public static int takematches = 0;

        static int Main( string[] args )
        {
            try
            {
                #region Command Line Parsing

                // Check for /? on the command line
                foreach ( string arg in args )
                {
                    if ( arg == "/?" )
                    {
                        return WriteError( );
                    }
                }

                string filename = string.Empty;
                string pattern = string.Empty;
                string[] options = null;
                RegexOptions regexoptions = RegexOptions.None;
                bool isredirected = ConsoleEx.InputRedirected;
                int redirectnum = ( isredirected ? 1 : 0 );
                string input = string.Empty;

                // Check and interpret command line arguments
                switch ( args.Length + redirectnum )
                {
                    case 2:
                        if ( isredirected )
                        {
                            pattern = args[0];
                        }
                        else
                        {
                            filename = args[0];
                            pattern = args[1];
                        }
                        break;
                    case 3:
                    case 4:
                    case 5:
                        if ( isredirected )
                        {
                            pattern = args[0];
                            options = args.Slice( 1, args.Length );
                        }
                        else
                        {
                            filename = args[0];
                            pattern = args[1];
                            options = args.Slice( 2, args.Length );
                        }
                        break;
                    default:
                        return WriteError( );
                }

                if ( options != null )
                {
                    foreach ( string option in options )
                    {
                        // Right now, /I is the only valid command line switch
                        switch ( option.ToUpper( ).Substring( 0, 2 ) )
                        {
                            case "/I":
                                regexoptions |= RegexOptions.IgnoreCase;
                                break;
                            case "/S":
                                try
                                {
                                    skipmatches = Convert.ToInt32( option.Substring( 3 ) );
                                }
                                catch ( Exception e )
                                {
                                    Console.Error.WriteLine( "Error: {0}", e.Message );
                                    return WriteError( "Invalid command line switch: " + option );
                                }
                                break;
                            case "/T":
                                try
                                {
                                    takematches = Convert.ToInt32( option.Substring( 3 ) );
                                }
                                catch ( Exception e )
                                {
                                    Console.Error.WriteLine( "Error: {0}", e.Message );
                                    return WriteError( "Invalid command line switch: " + option );
                                }
                                break;
                            default:
                                return WriteError( "Invalid command line " + ( option.Substring( 0, 1 ) == "/" ? "switch" : "argument" ) + ": " + option );
                        }
                    }
                }

                if ( isredirected )
                {
                    // Read the redirected Standard Input
                    input = Console.In.ReadToEnd( );
                }
                else
                {
                    // Check if the file name is valid
                    if ( filename.IndexOf( "/" ) > -1 )
                    {
                        return WriteError( );
                    }
                    if ( filename.IndexOfAny( "?*".ToCharArray( ) ) > -1 )
                    {
                        return WriteError( "Wildcards not allowed" );
                    }
                    // Check if the file exists
                    if ( File.Exists( filename ) )
                    {
                        // Read the file content
                        using ( StreamReader file = new StreamReader( filename ) )
                        {
                            input = file.ReadToEnd( );
                        }
                    }
                    else
                    {
                        return WriteError( "File not found: \"" + filename + "\"" );
                    }
                }

                #endregion Command Line Parsing

                // Now that the command line parsing is done, let's get some action
                if ( DisplayMatches( input, pattern, regexoptions ) == 0 )
                {
                    return WriteError( "No match found" );
                }
                else
                {
                    return 0;
                }
            }
            catch ( Exception e )
            {
                return WriteError( e.Message );
            }
        }

        // The main functionality: display all matching substrings
        public static int DisplayMatches( string haystack, string needle, RegexOptions options )
        {
            int counter = 0;
            int displayed = 0;
            // Get all matches
            MatchCollection matches = Regex.Matches( haystack, needle, options );
            if ( matches.Count > skipmatches )
            {
                foreach ( Match match in matches )
                {
                    if ( counter >= skipmatches && ( displayed < takematches || takematches == 0 ) )
                    {
                        Console.WriteLine( match.Value );
                        displayed += 1;
                    }
                    counter += 1;
                }
            }
            return displayed;
        }

        #region Redirection Detection

        // Code to detect redirection by Hans Passant on StackOverflow.com
        // http://stackoverflow.com/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected
        public static class ConsoleEx
        {
            public static bool OutputRedirected
            {
                get
                {
                    return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stdout ) );
                }
            }

            public static bool InputRedirected
            {
                get
                {
                    return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stdin ) );
                }
            }

            public static bool ErrorRedirected
            {
                get
                {
                    return FileType.Char != GetFileType( GetStdHandle( StdHandle.Stderr ) );
                }
            }

            // P/Invoke:
            private enum FileType { Unknown, Disk, Char, Pipe };
            private enum StdHandle { Stdin = -10, Stdout = -11, Stderr = -12 };

            [DllImport( "kernel32.dll" )]
            private static extern FileType GetFileType( IntPtr hdl );

            [DllImport( "kernel32.dll" )]
            private static extern IntPtr GetStdHandle( StdHandle std );
        }

        #endregion Redirection Detection

        #region Error Handling

        public static int WriteError( Exception e = null )
        {
            return WriteError( e == null ? null : e.Message );
        }

        public static int WriteError( string errorMessage )
        {
            Console.OpenStandardError( );
            if ( string.IsNullOrEmpty( errorMessage ) == false )
            {
                Console.Error.WriteLine( );
                Console.ForegroundColor = ConsoleColor.Red;
                Console.Error.Write( "ERROR: " );
                Console.ForegroundColor = ConsoleColor.White;
                Console.Error.WriteLine( errorMessage );
                Console.ResetColor( );
            }

            /*
            RxGrep,  Version 2.00
            Multi-line FindStr/Grep like tool

            Usage:   RXGREP  filename  pattern  [ /I ]  [ /S:nn ]  [ /T:nn ]
            or:      some_command  |  RXGREP  pattern  [ /I ]  [ /S:nn ]  [ /T:nn ]

            Where:   filename       is the file to be filtered
                     some_command   is the command whose standard output is to be filtered
                     pattern        is the search pattern (regular expression)
                     /I             makes the search case insensitive
                     /S:nn          Skip the first nn matches
                     /T:nn          Take only nn matches

            Example: ROBOCOPY D:\sourcedir E:\targetdir /NP /MIR |
                     RXGREP "\s+\d+\s+D:\\sourcedir\\[^\n\r]*\r\n([^\n\r\\]+\r\n)+"
                     (to be read as a single command line) will return something like:
                                     125    D:\sourcedir\subdir\
                        New File                 342        brandnewfile.ext
                        Newer                  4.06m        updatedfile.ext
                      *EXTRA File              2.40m        deletedfile.ext

            Check for redirection by Hans Passant on StackOverflow.com
            /questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected
            Array Slice extension by Sam Allen http://www.dotnetperls.com/array-slice

            Written by Rob van der Woude
            http://www.robvanderwoude.com
             */

            Console.Error.WriteLine( );
            Console.Error.WriteLine( "RxGrep,  Version 2.00" );
            Console.Error.WriteLine( "Multi-line FindStr/Grep like tool" );
            Console.Error.WriteLine( );
            Console.Error.Write( "Usage:   " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.WriteLine( "RXGREP  filename  pattern  [ /I ]  [ /S:nn ]  [ /T:nn ]" );
            Console.ResetColor( );
            Console.Error.Write( "or:      " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.WriteLine( "some_command  |  RXGREP  pattern  [ /I ]  [ /S:nn ]  [ /T:nn ]" );
            Console.ResetColor( );
            Console.Error.WriteLine( );
            Console.Error.Write( "Where:   " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "filename" );
            Console.ResetColor( );
            Console.Error.WriteLine( "       is the file to be filtered" );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "         some_command" );
            Console.ResetColor( );
            Console.Error.WriteLine( "   is the command whose standard output is to be filtered" );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "         pattern" );
            Console.ResetColor( );
            Console.Error.WriteLine( "        is the search pattern (regular expression)" );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "         /I" );
            Console.ResetColor( );
            Console.Error.Write( "             makes the search case " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "I" );
            Console.ResetColor( );
            Console.Error.WriteLine( "nsensitive" );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "         /S:nn          S" );
            Console.ResetColor( );
            Console.Error.Write( "kip the first " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "nn" );
            Console.ResetColor( );
            Console.Error.WriteLine( " matches" );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "         /T:nn          T" );
            Console.ResetColor( );
            Console.Error.Write( "ake only " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.Write( "nn" );
            Console.ResetColor( );
            Console.Error.WriteLine( " matches" );
            Console.Error.WriteLine( );
            Console.Error.Write( "Example: " );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.WriteLine( @"ROBOCOPY D:\sourcedir E:\targetdir /NP /MIR |" );
            Console.Error.WriteLine( @"         RXGREP ""\s+\d+\s+D:\\sourcedir\\[^\n\r]*\r\n([^\n\r\\]+\r\n)+""" );
            Console.ResetColor( );
            Console.Error.WriteLine( "         (to be read as a single command line) will return something like:" );
            Console.ForegroundColor = ConsoleColor.White;
            Console.Error.WriteLine( @"                         125    D:\sourcedir\subdir\" );
            Console.Error.WriteLine( "            New File                 342        brandnewfile.ext" );
            Console.Error.WriteLine( "            Newer                  4.06m        updatedfile.ext" );
            Console.Error.WriteLine( "          *EXTRA File              2.40m        deletedfile.ext" );
            Console.ResetColor( );
            Console.Error.WriteLine( );
            Console.Error.Write( "Check for redirection by Hans Passant on " );
            Console.ForegroundColor = ConsoleColor.DarkGray;
            Console.Error.WriteLine( "StackOverflow.com" );
            Console.Error.WriteLine( "/questions/3453220/how-to-detect-if-console-in-stdin-has-been-redirected" );
            Console.ResetColor( );
            Console.Error.Write( "Array Slice extension by Sam Allen " );
            Console.ForegroundColor = ConsoleColor.DarkGray;
            Console.Error.WriteLine( "http://www.dotnetperls.com/array-slice" );
            Console.ResetColor( );
            Console.Error.WriteLine( );
            Console.Error.WriteLine( "Written by Rob van der Woude" );
            Console.Error.Write( "http://www.robvanderwoude.com" );
            Console.OpenStandardOutput( );
            return 1;
        }

        #endregion Error Handling
    }

    #region Extensions

    // Array Slice
    // http://www.dotnetperls.com/array-slice
    public static class Extensions
    {
        /// <summary>
        /// Get the array slice between the two indexes.
        /// ... Inclusive for start index, exclusive for end index.
        /// </summary>
        public static T[] Slice<T>( this T[] source, int start, int end )
        {
            // Handles negative ends.
            if ( end < 0 )
            {
                end = source.Length + end;
            }
            int len = end - start;

            // Return new array.
            T[] res = new T[len];
            for ( int i = 0; i < len; i++ )
            {
                res[i] = source[i + start];
            }
            return res;
        }
    }

    #endregion Extensions
}

<h4>附件:<a href="/uploadfiles/2013/05/13/136845404490482.zip">源代码下载</a></h4>

标签:字符查找,grep,C#

收藏

0人收藏

支持

0

反对

0

相关聚客文章
  1. 米豆网 - 1000seo 发表 2012-08-03 14:53:27 c#时间格式
  2. skeet 发表 2012-03-06 19:54:54 Eduasync 20: Changes between the VS11 Preview and
  3. IT路人 发表 2013-07-05 05:00:00 利用C# .net在WP8里面异步加载任务
  4. welpher 发表 2012-03-06 01:34:51 Chrome下AJAX不成功
  5. efour 发表 2013-11-16 06:34:45 ExcelHelper
  6. 嘟嘟 发表 2013-09-08 04:59:01 c#坐标变换
  7. 逝去日子 发表 2014-08-27 13:11:55 asp之gridview学习小记
  8. 逝去日子 发表 2014-11-26 02:58:31 asp中隐藏按钮并响应回车事件
  9. 逝去日子 发表 2015-01-24 09:23:07 asp.net MVC4使用Entity连接mysql
  10. mengskysama 发表 2015-01-15 07:44:39 Java RSA/ECB/NoPadding in C# Python
  11. 博主 发表 2009-08-06 14:29:36 C#随机顺序输出数字 1~9 的算法
  12. root 发表 2015-04-19 07:38:01 C#获取程序所在目录路径

发表评论