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);
}
}
}
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.