Rob van der Woude's Scripting Pages
Powered by GeSHi

Source code for rxgrep.cs

(view source code of rxgrep.cs as plain text)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text.RegularExpressions;
  5.  
  6.  
  7. namespace RobvanderWoude
  8. {
  9. 	class RxGrep
  10. 	{
  11. 		static string progver = "2.03";
  12.  
  13. 		static int skipmatches = 0;
  14. 		static int takematches = 0;
  15. 		static int bytes = -1;
  16.  
  17.  
  18. 		static int Main( string[] args )
  19. 		{
  20. 			#region Initialize Variables
  21.  
  22. 			bool caseset = false;
  23. 			bool skipset = false;
  24. 			bool takeset = false;
  25. 			string filename = String.Empty;
  26. 			string pattern = String.Empty;
  27. 			string input = String.Empty;
  28. 			int redirectnum = ( Console.IsInputRedirected ? 1 : 0 );
  29. 			RegexOptions regexoptions = RegexOptions.None;
  30.  
  31. 			#endregion Initialize Variables
  32.  
  33.  
  34. 			//try
  35. 			{
  36.  
  37. 				#region Command Line Parsing
  38.  
  39. 				if ( args.Length + redirectnum < 2 )
  40. 				{
  41. 					return ShowHelp( );
  42. 				}
  43.  
  44. 				List<string> arguments = new List<string>( args );
  45. 				if ( arguments.Contains( "/?" ) )
  46. 				{
  47. 					return ShowHelp( );
  48. 				}
  49.  
  50. 				if ( !Console.IsInputRedirected )
  51. 				{
  52. 					filename = arguments[0];
  53. 					arguments.RemoveAt( 0 );
  54. 				}
  55. 				pattern = arguments[0];
  56. 				arguments.RemoveAt( 0 );
  57.  
  58. 				foreach ( string option in arguments )
  59. 				{
  60. 					switch ( option.ToUpper( ).Substring( 0, 2 ) )
  61. 					{
  62. 						case "/F":
  63. 							if ( bytes != -1 )
  64. 							{
  65. 								return ShowHelp( "Duplicate switch /F" );
  66. 							}
  67. 							try
  68. 							{
  69. 								bytes = Convert.ToInt32( option.Substring( 3 ) );
  70. 							}
  71. 							catch ( Exception e )
  72. 							{
  73. 								Console.Error.WriteLine( "Error: {0}", e.Message );
  74. 								return ShowHelp( String.Format( "Invalid command line switch \"{0}\"", option ) );
  75. 							}
  76. 							break;
  77. 						case "/I":
  78. 							if ( caseset )
  79. 							{
  80. 								return ShowHelp( "Duplicate switch /I" );
  81. 							}
  82. 							regexoptions |= RegexOptions.IgnoreCase;
  83. 							caseset = true;
  84. 							break;
  85. 						case "/S":
  86. 							if ( skipset )
  87. 							{
  88. 								return ShowHelp( "Duplicate switch /S" );
  89. 							}
  90. 							try
  91. 							{
  92. 								skipmatches = Convert.ToInt32( option.Substring( 3 ) );
  93. 							}
  94. 							catch ( Exception e )
  95. 							{
  96. 								Console.Error.WriteLine( "Error: {0}", e.Message );
  97. 								return ShowHelp( String.Format( "Invalid command line switch \"{0}\"", option ) );
  98. 							}
  99. 							break;
  100. 						case "/T":
  101. 							if ( takeset )
  102. 							{
  103. 								return ShowHelp( "Duplicate switch /T" );
  104. 							}
  105. 							try
  106. 							{
  107. 								takematches = Convert.ToInt32( option.Substring( 3 ) );
  108. 							}
  109. 							catch ( Exception e )
  110. 							{
  111. 								Console.Error.WriteLine( "Error: {0}", e.Message );
  112. 								return ShowHelp( String.Format( "Invalid command line switch \"{0}\"", option ) );
  113. 							}
  114. 							break;
  115. 						default:
  116. 							return ShowHelp( String.Format( "Invalid command line {0}: \"{1}\"", ( option[0] == '/' ? "switch" : "argument" ), option ) );
  117. 					}
  118. 				}
  119.  
  120. 				#endregion Command Line Parsing
  121.  
  122.  
  123. 				#region Command Line Arguments Validation
  124.  
  125. 				if ( Console.IsInputRedirected )
  126. 				{
  127. 					// Read the redirected Standard Input
  128. 					input = Console.In.ReadToEnd( );
  129. 					if ( bytes != -1 )
  130. 					{
  131. 						input = input.Substring( 0, Math.Min( bytes, input.Length ) );
  132. 					}
  133. 				}
  134. 				else
  135. 				{
  136. 					// Check if the file name is valid
  137. 					if ( filename.IndexOf( "/" ) > -1 )
  138. 					{
  139. 						return ShowHelp( );
  140. 					}
  141. 					if ( filename.IndexOfAny( "?*".ToCharArray( ) ) > -1 )
  142. 					{
  143. 						return ShowHelp( "Wildcards not allowed" );
  144. 					}
  145. 					// Check if the file exists
  146. 					if ( File.Exists( filename ) )
  147. 					{
  148. 						// Read the file content
  149. 						using ( StreamReader file = new StreamReader( filename ) )
  150. 						{
  151. 							if ( bytes == -1 )
  152. 							{
  153. 								input = file.ReadToEnd( );
  154. 							}
  155. 							else
  156. 							{
  157. 								char[] buffer = new char[bytes];
  158. 								file.Read( buffer, 0, bytes );
  159. 								input = String.Join( String.Empty, buffer );
  160. 							}
  161. 						}
  162. 					}
  163. 					else
  164. 					{
  165. 						return ShowHelp( String.Format( "File not found: \"{0}\"", filename ) );
  166. 					}
  167. 				}
  168.  
  169. 				#endregion Command Line Arguments Validation
  170.  
  171.  
  172. 				// Now that the command line parsing is done, let's get some action
  173. 				if ( DisplayMatches( input, pattern, regexoptions ) == 0 )
  174. 				{
  175. 					return ShowHelp( "No match found" );
  176. 				}
  177. 				else
  178. 				{
  179. 					return 0;
  180. 				}
  181. 			}
  182. 			/*
  183. 			catch ( Exception e )
  184. 			{
  185. 				return ShowHelp( e.Message );
  186. 			}
  187. 			*/
  188. 		}
  189.  
  190.  
  191. 		// The main functionality: display all matching substrings
  192. 		public static int DisplayMatches( string haystack, string needle, RegexOptions options )
  193. 		{
  194. 			int counter = 0;
  195. 			int displayed = 0;
  196. 			// Get all matches
  197. 			MatchCollection matches = Regex.Matches( haystack, needle, options );
  198. 			if ( matches.Count > skipmatches )
  199. 			{
  200. 				foreach ( Match match in matches )
  201. 				{
  202. 					if ( counter >= skipmatches && ( displayed < takematches || takematches == 0 ) )
  203. 					{
  204. 						Console.WriteLine( match.Value );
  205. 						displayed += 1;
  206. 					}
  207. 					counter += 1;
  208. 				}
  209. 			}
  210. 			return displayed;
  211. 		}
  212.  
  213.  
  214. 		#region Error Handling
  215.  
  216. 		public static int ShowHelp( params string[] errmsg )
  217. 		{
  218. 			#region Error Message
  219.  
  220. 			if ( errmsg.Length > 0 )
  221.  
  222. 			{
  223. 				List<string> errargs = new List<string>( errmsg );
  224. 				errargs.RemoveAt( 0 );
  225. 				Console.Error.WriteLine( );
  226. 				Console.ForegroundColor = ConsoleColor.Red;
  227. 				Console.Error.Write( "ERROR:\t" );
  228. 				Console.ForegroundColor = ConsoleColor.White;
  229. 				Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) );
  230. 				Console.ResetColor( );
  231. 			}
  232.  
  233. 			#endregion Error Message
  234.  
  235.  
  236. 			#region Help Text
  237.  
  238. 			/*
  239. 			RxGrep,  Version 2.03
  240. 			Multi-line FindStr/Grep like tool
  241.  
  242. 			Usage:   RXGREP  filename  pattern  [ options ]
  243. 			or:      command  |  RXGREP  pattern  [ options ]
  244.  
  245. 			Where:   filename   is the file to be filtered
  246. 			         command    is the command whose standard output is to be filtered
  247. 			         pattern    is the search pattern (regular expression)
  248.  
  249. 			Options: /F:nn      search only the First nn bytes
  250. 			         /I         case Insensitive search
  251. 			         /S:nn      Skip the first nn matches
  252. 			         /T:nn      Take only nn matches
  253.  
  254. 			Example: ROBOCOPY D:\sourcedir E:\targetdir /NP /MIR |
  255. 			         RXGREP "\s+\d+\s+D:\\sourcedir\\[^\n\r]*\r\n([^\n\r\\]+\r\n)+"
  256. 			         (to be read as a single command line) will return something like:
  257. 			                         125    D:\sourcedir\subdir\
  258. 			            New File                 342        brandnewfile.ext
  259. 			            Newer                  4.06m        updatedfile.ext
  260. 			          *EXTRA File              2.40m        deletedfile.ext
  261.  
  262. 			Notes:   If /F:nn is used and a file is specified, only the first nn bytes
  263. 			         of that file will be read; if the input is redirected, it is read
  264. 			         entirely, and then chopped to nn bytes before being searched.
  265. 			         Return code ("errorlevel") will be 1 in case of (command line)
  266. 			         errors or if no match was found, otherwise 0.
  267. 			         This version of the program requires .NET Framework 4.5.
  268.  
  269. 			Written by Rob van der Woude
  270. 			http://www.robvanderwoude.com
  271. 			 */
  272.  
  273. 			Console.Error.WriteLine( );
  274. 			Console.Error.WriteLine( "RxGrep,  Version {0}", progver );
  275. 			Console.Error.WriteLine( "Multi-line FindStr/Grep like tool" );
  276. 			Console.Error.WriteLine( );
  277.  
  278. 			Console.Error.Write( "Usage:   " );
  279. 			Console.ForegroundColor = ConsoleColor.White;
  280. 			Console.Error.WriteLine( "RXGREP  filename  pattern  [ options ]" );
  281. 			Console.ResetColor( );
  282.  
  283. 			Console.Error.Write( "or:      " );
  284. 			Console.ForegroundColor = ConsoleColor.White;
  285. 			Console.Error.WriteLine( "command | RXGREP  pattern  [ options ]" );
  286. 			Console.ResetColor( );
  287.  
  288. 			Console.Error.WriteLine( );
  289.  
  290. 			Console.Error.Write( "Where:   " );
  291. 			Console.ForegroundColor = ConsoleColor.White;
  292. 			Console.Error.Write( "filename" );
  293. 			Console.ResetColor( );
  294. 			Console.Error.WriteLine( "   is the file to be filtered" );
  295.  
  296. 			Console.ForegroundColor = ConsoleColor.White;
  297. 			Console.Error.Write( "         command" );
  298. 			Console.ResetColor( );
  299. 			Console.Error.WriteLine( "    is the command whose standard output is to be filtered" );
  300.  
  301. 			Console.ForegroundColor = ConsoleColor.White;
  302. 			Console.Error.Write( "         pattern" );
  303. 			Console.ResetColor( );
  304. 			Console.Error.WriteLine( "    is the search pattern (regular expression)" );
  305.  
  306. 			Console.Error.WriteLine( );
  307.  
  308. 			Console.Error.Write( "Options: " );
  309. 			Console.ForegroundColor = ConsoleColor.White;
  310. 			Console.Error.Write( "/F:nn" );
  311. 			Console.ResetColor( );
  312. 			Console.Error.Write( "      search only the " );
  313. 			Console.ForegroundColor = ConsoleColor.White;
  314. 			Console.Error.Write( "F" );
  315. 			Console.ResetColor( );
  316. 			Console.Error.Write( "irst " );
  317. 			Console.ForegroundColor = ConsoleColor.White;
  318. 			Console.Error.Write( "nn" );
  319. 			Console.ResetColor( );
  320. 			Console.Error.WriteLine( " bytes" );
  321.  
  322. 			Console.ForegroundColor = ConsoleColor.White;
  323. 			Console.Error.Write( "         /I" );
  324. 			Console.ResetColor( );
  325. 			Console.Error.Write( "         case " );
  326. 			Console.ForegroundColor = ConsoleColor.White;
  327. 			Console.Error.Write( "I" );
  328. 			Console.ResetColor( );
  329. 			Console.Error.WriteLine( "nsensitive search" );
  330.  
  331. 			Console.ForegroundColor = ConsoleColor.White;
  332. 			Console.Error.Write( "         /S:nn      S" );
  333. 			Console.ResetColor( );
  334. 			Console.Error.Write( "kip the first " );
  335. 			Console.ForegroundColor = ConsoleColor.White;
  336. 			Console.Error.Write( "nn" );
  337. 			Console.ResetColor( );
  338. 			Console.Error.WriteLine( " matches" );
  339.  
  340. 			Console.ForegroundColor = ConsoleColor.White;
  341. 			Console.Error.Write( "         /T:nn      T" );
  342. 			Console.ResetColor( );
  343. 			Console.Error.Write( "ake only " );
  344. 			Console.ForegroundColor = ConsoleColor.White;
  345. 			Console.Error.Write( "nn" );
  346. 			Console.ResetColor( );
  347. 			Console.Error.WriteLine( " matches" );
  348.  
  349. 			Console.Error.WriteLine( );
  350.  
  351. 			Console.Error.Write( "Example: " );
  352. 			Console.ForegroundColor = ConsoleColor.White;
  353. 			Console.Error.WriteLine( @"ROBOCOPY D:\sourcedir E:\targetdir /NP /MIR |" );
  354.  
  355. 			Console.Error.WriteLine( @"         RXGREP ""\s+\d+\s+D:\\sourcedir\\[^\n\r]*\r\n([^\n\r\\]+\r\n)+""" );
  356. 			Console.ResetColor( );
  357.  
  358. 			Console.Error.WriteLine( "         (to be read as a single command line) will return something like:" );
  359.  
  360. 			Console.ForegroundColor = ConsoleColor.White;
  361. 			Console.Error.WriteLine( @"                         125    D:\sourcedir\subdir\" );
  362.  
  363. 			Console.Error.WriteLine( "            New File                 342        brandnewfile.ext" );
  364.  
  365. 			Console.Error.WriteLine( "            Newer                  4.06m        updatedfile.ext" );
  366.  
  367. 			Console.Error.WriteLine( "          *EXTRA File              2.40m        deletedfile.ext" );
  368. 			Console.ResetColor( );
  369.  
  370. 			Console.Error.WriteLine( );
  371.  
  372. 			Console.Error.Write( "Notes:   If " );
  373. 			Console.ForegroundColor = ConsoleColor.White;
  374. 			Console.Error.Write( "/F:nn" );
  375. 			Console.ResetColor( );
  376. 			Console.Error.Write( " is used and a file is specified, only the first " );
  377. 			Console.ForegroundColor = ConsoleColor.White;
  378. 			Console.Error.Write( "nn" );
  379. 			Console.ResetColor( );
  380. 			Console.Error.WriteLine( " bytes" );
  381.  
  382. 			Console.Error.WriteLine( "         of that file will be read; if the input is redirected, it is read" );
  383.  
  384. 			Console.Error.Write( "         entirely, and then chopped to " );
  385. 			Console.ForegroundColor = ConsoleColor.White;
  386. 			Console.Error.Write( "nn" );
  387. 			Console.ResetColor( );
  388. 			Console.Error.WriteLine( " bytes before being searched." );
  389.  
  390. 			Console.Error.WriteLine( "         Return code (\"errorlevel\") will be 1 in case of (command line)" );
  391.  
  392. 			Console.Error.WriteLine( "         errors or if no match was found, otherwise 0." );
  393.  
  394. 			Console.Error.WriteLine( "         This version of the program requires .NET Framework 4.5." );
  395.  
  396. 			Console.Error.WriteLine( );
  397.  
  398. 			Console.Error.WriteLine( "Written by Rob van der Woude" );
  399.  
  400. 			Console.Error.WriteLine( "http://www.robvanderwoude.com" );
  401.  
  402. 			#endregion Help Text
  403.  
  404.  
  405. 			return 1;
  406. 		}
  407.  
  408. 		#endregion Error Handling
  409. 	}
  410. }
  411.  

page last uploaded: 2017-08-21, 14:26