Grep pour windows

Contenu du snippet

Il s'agit d'un programme qui recherche et met en valeur des chaînes de caractères dans des fichiers ou dans un flux capturé en pipe.
J'avais besoin d'un équivalent du grep des UNIX que je ne trouvais pas sous windows.

Source / Exemple :


using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Generic;

namespace Grep
{
	class Program
	{
		static RegexOptions regexOptions = 0;
		static bool displayLineNumber = false;
		static ConsoleColor lineNumberColor;
		static ConsoleColor highlightColor;
		static bool CountOccurences = false;
		static bool displayOccurences = true;
		static bool grepConsole = false;
		static SearchOption fileSearchOptions = SearchOption.TopDirectoryOnly;
		static Regex searches;
		static TextWriter output;
		
		/// <summary>
		/// Permet de parser les arguments de la ligne de commande
		/// </summary>
		static Regex argsParser = new Regex(@"^/(?<name>\w+)(:(?<value>\w+))?$", RegexOptions.Singleline | RegexOptions.ExplicitCapture);

		static void Main ( string[] args )
		{
			if (args.Length < 2) {
				help(null);
			}

			string wildcard = args[0];
			//si le chemin commence par /c
			if (wildcard.StartsWith("/c")) grepConsole = true;
			//extrait le nom du répertoire et le masque de la 
			string files = Path.GetFileName(wildcard);
			string path = wildcard.Substring(0, wildcard.Length - files.Length);
			if (path == string.Empty) path = ".";

			//les les options dans les paramètres
			ReadOptions(args);
			output = new StreamWriter(Console.OpenStandardOutput());
			if (output==null) output = Console.Out;

			if (grepConsole) {
				//dans le cas d'une lecture du pipe, ouvre le pipe
				using (TextReader s = new StreamReader(Console.OpenStandardInput())) {
					//puis le filtre
					ExtractDatasFromStream(s);
				}
			} else {
				//dans le cas d'une lecture fichiers
				//vérifie l'existence des fichiers
				if (!Directory.Exists(path)) {
					help("Le chemin spécifié n'existe pas");
				}

				//récupère la liste des fichiers à filtrer
				string[] filenames = Directory.GetFiles(path, files, fileSearchOptions);

				foreach (string filename in filenames) {
					//affiche le nom du fichier
					Console.WriteLine("-- {0} {1}", filename, new string('-', filename.Length < 74 ? 76 - filename.Length : 2));

					//ouvre le fichier
					using (TextReader s = new StreamReader(File.OpenRead(Path.Combine(path, filename)))) {
						//puis le filtre
						ExtractDatasFromStream(s);
					}
				}
			}
		}

		/// <summary>
		/// Extrait les données du flux en fonction des recherches indiquées
		/// </summary>
		/// <param name="s">flux à filter</param>
		private static void ExtractDatasFromStream ( TextReader s )
		{
			ConsoleColor defaultConsoleColor = Console.ForegroundColor;
			int i = 0;
			int occurences = 0;
			bool first = true;
			while (true) {
				i++;
				string line = s.ReadLine();
				if (line == null) break;
				MatchCollection matches = searches.Matches(line);
				if (matches.Count > 0) {
					//affiche le numéro de ligne
					if (displayLineNumber) {
						Console.ForegroundColor = lineNumberColor;
						if (!displayOccurences && !first) {
							output.Write(",");
						} else {
							first = false;
						}
						output.Write(i);
						if (displayOccurences) {
							output.Write(":");
						}

						output.Flush();
						Console.ForegroundColor = defaultConsoleColor;
					}
					int pos = 0;
					//affiche les lignes sur lesquelles la valeur a été trouvée
					if (displayOccurences) {
						foreach (Match match in matches) {
							//met en valeur la valeur
							output.Write(line.Substring(pos, match.Index - pos));
							output.Flush();
							Console.ForegroundColor = highlightColor;
							output.Write(line.Substring(match.Index, match.Length));
							output.Flush();
							//revient à la couleur par défaut
							Console.ForegroundColor = defaultConsoleColor;
							pos = match.Index + match.Length;
						}
						output.WriteLine(line.Substring(pos));
						output.Flush();
					}
					occurences += matches.Count;
				}
			}
			if (CountOccurences) {
				if (displayOccurences || displayLineNumber) output.WriteLine();
				output.WriteLine("{0} occurences", occurences);
				output.Flush();
			}
		}

		/// <summary>
		/// Lit les options dans les arguments
		/// </summary>
		/// <param name="args"></param>
		private static void ReadOptions ( string[] args )
		{
			lineNumberColor = Console.ForegroundColor;
			highlightColor = Console.ForegroundColor;

			List<string> stringSearches = new List<string>();
			bool inOptions = true;
			for (int i = 1; i < args.Length; i++) {
				if (inOptions) {
					Match m = argsParser.Match(args[i]);
					if (m.Success) {
						switch (m.Groups["name"].Value) {
							case "i": regexOptions |= RegexOptions.IgnoreCase;
								break;
							case "h":
								if (m.Groups["value"].Success) {
									highlightColor = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), m.Groups["value"].Value, true);
								} else {
									help("l'argument h doit avoir une valeur");
								}
								break;
							case "n": displayLineNumber = true;
								if (m.Groups["value"].Success) {
									lineNumberColor = (ConsoleColor)Enum.Parse(typeof (ConsoleColor), m.Groups["value"].Value, true);
								}
								break;
							case "d": fileSearchOptions = SearchOption.AllDirectories;
								break;
							case "o": CountOccurences = true;
								break;
							case "O": CountOccurences = true; displayOccurences = false;
								break;
						}
						continue;
					}
					inOptions = false;
				}
				stringSearches.Add(args[i]);
			}
			if (stringSearches.Count == 0)
				help("La ligne de commande doit contenir au moins une chaîne de recherche");
			searches = new Regex("(" + string.Join("|", stringSearches.ToArray()) + ")", regexOptions);
		}

		/// <summary>
		/// Affiche l'aide et cort du programme
		/// </summary>
		/// <param name="message">Message à afficher avant l'aide</param>
		private static void help (string message)
		{
			if (message != null) {
				Console.WriteLine(message);
				Console.WriteLine();
			}
			Console.WriteLine("GREP");
			Console.WriteLine("Filtre les fichiers en fonction de la chaîne de recherche spécifiée");
			Console.WriteLine();
			Console.WriteLine("Syntaxes :");
			Console.WriteLine("\t GREP [chemin\\]masque /i [/n[:couleur]] /h:couleur chaine1 [chaine2 [chaine3...]]");
			Console.WriteLine("\t pipe | GREP /c /d /i [/n[:couleur]] /h:couleur chaine1 [chaine2 [chaine3...]]");
			Console.WriteLine();
			Console.WriteLine("Arguments : ");
			Console.WriteLine("\t/c\tFiltre le pipe");
			Console.WriteLine("\t/s\tRecherche dans les sous répertoires");
			Console.WriteLine("\t/i\tPermet d'ignorer la casse");
			Console.WriteLine("\t/n\tAffiche les numéros de ligne");
			Console.WriteLine("\t/h\tChange la couleur de la valeur trouvée");
			Console.WriteLine("\t/o\tCompte le nombre d'occurences trouvées");
			Console.WriteLine("\t/O\tCompte le nombre d'occurences trouvées sans les afficher");

			Environment.Exit(0);
		}
	}
}

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.