• 欢迎访问开心洋葱网站,在线教程,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站,欢迎加入开心洋葱 QQ群
  • 为方便开心洋葱网用户,开心洋葱官网已经开启复制功能!
  • 欢迎访问开心洋葱网站,手机也能访问哦~欢迎加入开心洋葱多维思维学习平台 QQ群
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏开心洋葱吧~~~~~~~~~~~~~!
  • 由于近期流量激增,小站的ECS没能经的起亲们的访问,本站依然没有盈利,如果各位看如果觉着文字不错,还请看官给小站打个赏~~~~~~~~~~~~~!

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

OC/C/C++ 水墨上仙 1355次浏览

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
}

附件:源代码下载


开心洋葱 , 版权所有丨如未注明 , 均为原创丨未经授权请勿修改 , 转载请注明C#在多行字符串中查找指定信息,类似linux下的grep功能
喜欢 (0)
加载中……