返回顶部

收藏

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. 博主 发表 2013-12-26 15:14:00 C#中的ThenBy是如何实现的
  2. 博主 发表 2013-08-02 07:00:00 C# Url Encoding的一些问题
  3. licstar 发表 2013-04-05 15:07:13 字符编码的那些事——原来C#、Java的一个char并不是对应一个显示字符
  4. 博主 发表 2014-08-01 00:00:00 给 c# 程序员的十个重要提示
  5. 博主 发表 2008-11-13 22:59:01 CLR Via C#(Second Edition)
  6. georgexsh 发表 2010-05-18 06:48:18 grep匹配tab
  7. root 发表 2015-04-16 04:58:01 c#结束winword.exe进程、
  8. root 发表 2015-04-20 10:26:01 在C#用HttpWebRequest中发送GET/HTTP/HTTPS请求
  9. root 发表 2015-04-23 06:50:01 C#实现WinForm窗体逐渐显示效果
  10. root 发表 2015-04-28 02:30:01 C#获取相对路径
  11. 博主 发表 2014-01-06 00:00:00 Exit Status of Grep in While in shell command
  12. chanext 发表 2012-08-25 17:32:00 Orchard 模块开发 环境的搭建和调试工作

发表评论