private IEnumerable <GrepMatch> TextSearchIterator(int lineNumber, int filePosition, string text, string searchText, GrepSearchOption searchOptions) { var lineEndIndexes = GetLineEndIndexes(initParams.VerboseMatchCount && lineNumber == -1 ? text : null); bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); StringComparison comparisonType = searchOptions.HasFlag(GrepSearchOption.CaseSensitive) ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase; if (searchOptions.HasFlag(GrepSearchOption.BooleanOperators)) { Utils.ParseBooleanOperators(searchText, out List <string> andClauses, out List <string> orClauses); if (andClauses != null && andClauses.Count > 1) { return(TextSearchIteratorAnd(lineNumber, filePosition, text, andClauses, lineEndIndexes, isWholeWord, comparisonType)); } if (orClauses != null && orClauses.Count > 1) { return(TextSearchIteratorOr(lineNumber, filePosition, text, orClauses, lineEndIndexes, isWholeWord, comparisonType)); } } return(TextSearchIterator(lineNumber, filePosition, text, searchText, lineEndIndexes, isWholeWord, comparisonType)); }
private IEnumerable <GrepMatch> TextSearchIterator(int lineNumber, int filePosition, string text, string searchText, GrepSearchOption searchOptions) { var lineEndIndexes = GetLineEndIndexes(initParams.VerboseMatchCount && lineNumber == -1 ? text : null); int index = 0; bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); StringComparison comparisonType = searchOptions.HasFlag(GrepSearchOption.CaseSensitive) ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase; while (index >= 0) { index = text.IndexOf(searchText, index, comparisonType); if (index >= 0) { if (isWholeWord && (!Utils.IsValidBeginText(text.Substring(0, index)) || !Utils.IsValidEndText(text.Substring(index + searchText.Length)))) { index++; continue; } if (initParams.VerboseMatchCount && lineEndIndexes.Count > 0) { lineNumber = lineEndIndexes.FindIndex(i => i > index) + 1; } yield return(new GrepMatch(lineNumber, index + filePosition, searchText.Length)); index++; } } }
private IEnumerable <GrepMatch> RegexSearchIterator(int lineNumber, int filePosition, string text, string searchPattern, GrepSearchOption searchOptions) { RegexOptions regexOptions = RegexOptions.None; if (!searchOptions.HasFlag(GrepSearchOption.CaseSensitive)) { regexOptions |= RegexOptions.IgnoreCase; } if (searchOptions.HasFlag(GrepSearchOption.Multiline)) { regexOptions |= RegexOptions.Multiline; } if (searchOptions.HasFlag(GrepSearchOption.SingleLine)) { regexOptions |= RegexOptions.Singleline; } bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); if (searchOptions.HasFlag(GrepSearchOption.BooleanOperators)) { BooleanExpression exp = new BooleanExpression(); if (exp.TryParse(searchPattern)) { return(RegexSearchIteratorBoolean(lineNumber, filePosition, text, exp, isWholeWord, regexOptions)); } } return(RegexSearchIterator(lineNumber, filePosition, text, searchPattern, isWholeWord, regexOptions)); }
public bool Replace(Stream readStream, Stream writeStream, string searchPattern, string replacePattern, SearchType searchType, GrepSearchOption searchOptions, Encoding encoding, IEnumerable <GrepMatch> replaceItems) { SearchDelegates.DoReplace replaceMethod = DoTextReplace; switch (searchType) { case SearchType.PlainText: replaceMethod = DoTextReplace; break; case SearchType.Regex: replaceMethod = DoRegexReplace; break; case SearchType.XPath: replaceMethod = DoXPathReplace; break; case SearchType.Soundex: replaceMethod = DoFuzzyReplace; break; } if (searchOptions.HasFlag(GrepSearchOption.Multiline) || searchType == SearchType.XPath) { return(ReplaceMultiline(readStream, writeStream, searchPattern, replacePattern, searchOptions, replaceMethod, encoding, replaceItems)); } else { return(Replace(readStream, writeStream, searchPattern, replacePattern, searchOptions, replaceMethod, encoding, replaceItems)); } }
public List <GrepSearchResult> Search(Stream input, string fileName, string searchPattern, SearchType searchType, GrepSearchOption searchOptions, Encoding encoding) { SearchDelegates.DoSearch searchMethod = DoTextSearch; switch (searchType) { case SearchType.PlainText: searchMethod = DoTextSearch; break; case SearchType.Regex: searchMethod = DoRegexSearch; break; case SearchType.XPath: searchMethod = DoXPathSearch; break; case SearchType.Soundex: searchMethod = DoFuzzySearch; break; } if (searchOptions.HasFlag(GrepSearchOption.Multiline) || searchType == SearchType.XPath) { return(SearchMultiline(input, fileName, searchPattern, searchOptions, searchMethod, encoding)); } else { return(Search(input, fileName, searchPattern, searchOptions, searchMethod, encoding)); } }
public List <GrepSearchResult> CaptureGroupSearch(IEnumerable <string> files, string filePatternInclude, GrepSearchOption searchOptions, SearchType searchType, string searchPattern, int codePage) { searchResults.Clear(); if (files == null || !files.Any()) { return(searchResults); } Utils.CancelSearch = false; try { foreach (string filePath in files) { string fileName = Path.GetFileName(filePath); string modSearchPattern = Regex.Replace(fileName, filePatternInclude, searchPattern, RegexOptions.IgnoreCase, TimeSpan.FromSeconds(4.0)); if (string.IsNullOrEmpty(modSearchPattern)) { continue; } else if (searchType == SearchType.Regex && !Utils.ValidateRegex(modSearchPattern)) { logger.Error($"Capture group search pattern is not a valid regular expression: '{modSearchPattern}'"); continue; } Search(filePath, searchType, modSearchPattern, searchOptions, codePage); if (searchOptions.HasFlag(GrepSearchOption.StopAfterFirstMatch) && searchResults.Count > 0) { break; } if (Utils.CancelSearch) { break; } } } catch (Exception ex) { logger.Error(ex, "Failed in capture group search"); } finally { if (cancellationTokenSource != null) { cancellationTokenSource.Dispose(); cancellationTokenSource = null; } GrepEngineFactory.UnloadEngines(); } return(new List <GrepSearchResult>(searchResults)); }
public List <GrepSearchResult> ListFiles(IEnumerable <FileData> files, GrepSearchOption searchOptions, int codePage) { searchResults.Clear(); if (files == null) { return(searchResults); } int successful = 0; foreach (FileData fileInfo in files) { ProcessedFile(this, new ProgressStatus(true, searchResults.Count, successful, null, fileInfo.FullName)); Encoding encoding = Encoding.Default; if (codePage > -1) { encoding = Encoding.GetEncoding(codePage); } try { if (GrepSettings.Instance.Get <bool>(GrepSettings.Key.DetectEncodingForFileNamePattern)) { if (codePage == -1 && !fileInfo.FullName.Contains(ArchiveDirectory.ArchiveSeparator) && !Utils.IsArchive(fileInfo.FullName) && !Utils.IsBinary(fileInfo.FullName) && !Utils.IsPdfFile(fileInfo.FullName)) { encoding = Utils.GetFileEncoding(fileInfo.FullName); } } searchResults.Add(new GrepSearchResult(fileInfo, encoding)); successful++; } catch (Exception ex) { // will catch file not found errors (Everything search): logger.Error(ex, "Failed in ListFiles"); fileInfo.ErrorMsg = ex.Message; AddSearchResult(new GrepSearchResult(fileInfo, encoding)); } if (searchOptions.HasFlag(GrepSearchOption.StopAfterFirstMatch)) { break; } if (Utils.CancelSearch) { break; } } ProcessedFile(this, new ProgressStatus(false, searchResults.Count, successful, searchResults, null)); return(new List <GrepSearchResult>(searchResults)); }
private IEnumerable <GrepMatch> TextSearchIterator(int lineNumber, int filePosition, string text, string searchText, GrepSearchOption searchOptions) { var lineEndIndexes = GetLineEndIndexes(initParams.VerboseMatchCount && lineNumber == -1 ? text : null); bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); StringComparison comparisonType = searchOptions.HasFlag(GrepSearchOption.CaseSensitive) ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase; if (searchOptions.HasFlag(GrepSearchOption.BooleanOperators)) { BooleanExpression exp = new BooleanExpression(); if (exp.TryParse(searchText)) { return(TextSearchIteratorBoolean(lineNumber, filePosition, text, exp, lineEndIndexes, isWholeWord, comparisonType)); } } return(TextSearchIterator(lineNumber, filePosition, text, searchText, lineEndIndexes, isWholeWord, comparisonType)); }
private IEnumerable <GrepMatch> RegexSearchIterator(int lineNumber, int filePosition, string text, string searchPattern, GrepSearchOption searchOptions) { RegexOptions regexOptions = RegexOptions.None; if (!searchOptions.HasFlag(GrepSearchOption.CaseSensitive)) { regexOptions |= RegexOptions.IgnoreCase; } if (searchOptions.HasFlag(GrepSearchOption.Multiline)) { regexOptions |= RegexOptions.Multiline; } if (searchOptions.HasFlag(GrepSearchOption.SingleLine)) { regexOptions |= RegexOptions.Singleline; } bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); if (searchOptions.HasFlag(GrepSearchOption.BooleanOperators)) { Utils.ParseBooleanOperators(searchPattern, out List <string> andClauses, out List <string> orClauses); if (andClauses != null && andClauses.Count > 1) { return(RegexSearchIteratorAnd(lineNumber, filePosition, text, andClauses, isWholeWord, regexOptions)); } if (orClauses != null && orClauses.Count > 1) { return(RegexSearchIteratorOr(lineNumber, filePosition, text, orClauses, isWholeWord, regexOptions)); } } return(RegexSearchIterator(lineNumber, filePosition, text, searchPattern, isWholeWord, regexOptions)); }
private IEnumerable <GrepMatch> FuzzySearchIterator(int lineNumber, int filePosition, string text, string searchPattern, GrepSearchOption searchOptions) { var lineEndIndexes = GetLineEndIndexes(initParams.VerboseMatchCount && lineNumber == -1 ? text : null); if (fuzzyMatchEngine == null) { fuzzyMatchEngine = new GoogleMatch(); } fuzzyMatchEngine.Match_Threshold = initParams.FuzzyMatchThreshold; bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); int counter = 0; while (counter < text.Length) { int matchLocation = fuzzyMatchEngine.match_main(text.Substring(counter), searchPattern, counter); if (matchLocation == -1) { break; } if (isWholeWord && !Utils.IsValidBeginText(text.Substring(counter).Substring(0, matchLocation))) { counter = counter + matchLocation + searchPattern.Length; continue; } int matchLength = fuzzyMatchEngine.match_length(text.Substring(counter), searchPattern, matchLocation, isWholeWord, initParams.FuzzyMatchThreshold); if (matchLength == -1) { counter = counter + matchLocation + searchPattern.Length; continue; } if (initParams.VerboseMatchCount && lineEndIndexes.Count > 0) { lineNumber = lineEndIndexes.FindIndex(i => i > matchLocation + counter) + 1; } yield return(new GrepMatch(searchPattern, lineNumber, matchLocation + filePosition + counter, matchLength)); counter = counter + matchLocation + matchLength; } }
protected string DoRegexReplace(int lineNumber, int filePosition, string text, string searchPattern, string replacePattern, GrepSearchOption searchOptions, IEnumerable <GrepMatch> replaceItems) { string result = text; RegexOptions regexOptions = RegexOptions.None; if (!searchOptions.HasFlag(GrepSearchOption.CaseSensitive)) { regexOptions |= RegexOptions.IgnoreCase; } if (searchOptions.HasFlag(GrepSearchOption.Multiline)) { regexOptions |= RegexOptions.Multiline; } if (searchOptions.HasFlag(GrepSearchOption.SingleLine)) { regexOptions |= RegexOptions.Singleline; } bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); if (isWholeWord) { if (!searchPattern.Trim().StartsWith("\\b")) { searchPattern = "\\b" + searchPattern.Trim(); } if (!searchPattern.Trim().EndsWith("\\b")) { searchPattern = searchPattern.Trim() + "\\b"; } } // check this block of text for any matches that are marked for replace // just return the original text if not var matches = RegexSearchIterator(lineNumber, filePosition, text, searchPattern, searchOptions); var toDo = replaceItems.Intersect(matches); if (toDo.Any(r => r.ReplaceMatch)) { // Issue #210 .net regex will only match the $ end of line token with a \n, not \r\n or \r bool convertToWindowsNewline = false; string searchPatternForReplace = searchPattern; if (searchPattern.Contains("$") && text.Contains("\r\n")) { convertToWindowsNewline = true; searchPatternForReplace = searchPattern.Replace("\r\n", "\n"); replacePattern = replacePattern.Replace("\r\n", "\n"); text = text.Replace("\r\n", "\n"); } // because we're possibly altering the new line chars, the match.Index in Regex.Replace // may not match the startPos in the GrepMatch, but the order of the matches should be // the same. So get the indexes of matches to change in this text block var indexes = toDo.Select((item, index) => new { item, index }).Where(t => t.item.ReplaceMatch).Select(t => t.index).ToList(); int matchIndex = 0; string replaceText = Regex.Replace(text, searchPatternForReplace, (match) => { if (indexes.Contains(matchIndex++)) { var pattern = DoPatternReplacement(match.Value, replacePattern); return(match.Result(pattern)); } else { return(match.Value); } }, regexOptions, MatchTimeout); if (convertToWindowsNewline) { replaceText = replaceText.Replace("\n", "\r\n"); } result = replaceText; } return(result); }
private void Search(string file, SearchType searchType, string searchPattern, GrepSearchOption searchOptions, int codePage) { try { ProcessedFile(this, new ProgressStatus(true, processedFilesCount, foundfilesCount, null, file)); IGrepEngine engine = GrepEngineFactory.GetSearchEngine(file, SearchParams, FileFilter); Interlocked.Increment(ref processedFilesCount); bool isArchive = file.Contains(ArchiveDirectory.ArchiveSeparator); Encoding encoding = Encoding.Default; if (codePage > -1) { encoding = Encoding.GetEncoding(codePage); } else if (!isArchive && !Utils.IsBinary(file) && !Utils.IsPdfFile(file)) { encoding = Utils.GetFileEncoding(file); } if (Utils.CancelSearch) { if (cancellationTokenSource != null) { cancellationTokenSource.Cancel(); } return; } List <GrepSearchResult> fileSearchResults = null; if (isArchive) { fileSearchResults = ArchiveEngine.Search(engine, file, searchPattern, searchType, searchOptions, encoding); } else { fileSearchResults = engine.Search(file, searchPattern, searchType, searchOptions, encoding); } if (fileSearchResults != null && fileSearchResults.Count > 0) { AddSearchResults(fileSearchResults); } int hits = fileSearchResults.Where(r => r.IsSuccess).Count(); Interlocked.Add(ref foundfilesCount, hits); ProcessedFile(this, new ProgressStatus(false, processedFilesCount, foundfilesCount, fileSearchResults, file)); GrepEngineFactory.ReturnToPool(file, engine); } catch (Exception ex) { logger.Log <Exception>(LogLevel.Error, ex.Message, ex); AddSearchResult(new GrepSearchResult(file, searchPattern, ex.Message, false)); if (ProcessedFile != null) { List <GrepSearchResult> _results = new List <GrepSearchResult> { new GrepSearchResult(file, searchPattern, ex.Message, false) }; ProcessedFile(this, new ProgressStatus(false, processedFilesCount, foundfilesCount, _results, file)); } } finally { if (searchOptions.HasFlag(GrepSearchOption.StopAfterFirstMatch) && searchResults.Count > 0) { if (cancellationTokenSource != null) { cancellationTokenSource.Cancel(); } } } }
/// <summary> /// Searches folder for files whose content matches regex /// </summary> /// <param name="files">Files to search in. If one of the files does not exist or is open, it is skipped.</param> /// <param name="searchRegex">Regex pattern</param> /// <returns>List of results. If nothing is found returns empty list</returns> public List <GrepSearchResult> Search(IEnumerable <string> files, SearchType searchType, string searchPattern, GrepSearchOption searchOptions, int codePage) { searchResults.Clear(); if (files == null) { return(searchResults); } Utils.CancelSearch = false; if (searchPattern == null || searchPattern.Trim() == "") { int count = 0; foreach (string file in files) { count++; ProcessedFile(this, new ProgressStatus(true, searchResults.Count, count, null, file)); Encoding encoding = Encoding.Default; if (codePage > -1) { encoding = Encoding.GetEncoding(codePage); } try { if (GrepSettings.Instance.Get <bool>(GrepSettings.Key.DetectEncodingForFileNamePattern)) { if (codePage == -1 && !Utils.IsArchive(file) && !Utils.IsBinary(file) && !Utils.IsPdfFile(file)) { encoding = Utils.GetFileEncoding(file); } } searchResults.Add(new GrepSearchResult(file, searchPattern, null, encoding)); } catch (Exception ex) { // will catch file not found errors (Everything search): logger.Error(ex, "Failed in File Search"); AddSearchResult(new GrepSearchResult(file, searchPattern, ex.Message, false)); } if (searchOptions.HasFlag(GrepSearchOption.StopAfterFirstMatch)) { break; } if (Utils.CancelSearch) { break; } } ProcessedFile(this, new ProgressStatus(false, searchResults.Count, count, searchResults, null)); return(new List <GrepSearchResult>(searchResults)); } else { processedFilesCount = 0; foundfilesCount = 0; try { if (SearchParams.SearchParallel) { cancellationTokenSource = new CancellationTokenSource(); ParallelOptions po = new ParallelOptions { MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount * 4 / 5), CancellationToken = cancellationTokenSource.Token }; Parallel.ForEach(files, po, f => Search(f, searchType, searchPattern, searchOptions, codePage)); } else { foreach (var file in files) { Search(file, searchType, searchPattern, searchOptions, codePage); if (searchOptions.HasFlag(GrepSearchOption.StopAfterFirstMatch) && searchResults.Count > 0) { break; } if (Utils.CancelSearch) { break; } } } } catch (OperationCanceledException) { // expected for stop after first match or user cancel } catch (Exception ex) { logger.Error(ex, "Failed in search in files"); } finally { if (cancellationTokenSource != null) { cancellationTokenSource.Dispose(); cancellationTokenSource = null; } GrepEngineFactory.UnloadEngines(); } return(new List <GrepSearchResult>(searchResults)); } }
private void Search(string file, SearchType searchType, string searchPattern, GrepSearchOption searchOptions, int codePage) { try { ProcessedFile(this, new ProgressStatus(true, processedFilesCount, foundfilesCount, null, file)); bool isArchive = Utils.IsArchive(file); Encoding encoding = Encoding.Default; if (codePage > -1) { encoding = Encoding.GetEncoding(codePage); } else if (!isArchive && !Utils.IsBinary(file) && !Utils.IsPdfFile(file)) { encoding = Utils.GetFileEncoding(file); } if (Utils.CancelSearch) { if (cancellationTokenSource != null) { cancellationTokenSource.Cancel(); } return; } IGrepEngine engine = GrepEngineFactory.GetSearchEngine(file, SearchParams, FileFilter, searchType); if (isArchive && engine is ArchiveEngine archiveEngine) { archiveEngine.SetSearchOptions(FileFilter, SearchParams); archiveEngine.StartingFileSearch += ArchiveEngine_StartingFileSearch; foreach (var fileSearchResults in archiveEngine.Search(file, searchPattern, searchType, searchOptions, encoding)) { if (fileSearchResults != null && fileSearchResults.Count > 0) { AddSearchResults(fileSearchResults); } int hits = fileSearchResults.Where(r => r.IsSuccess).Count(); Interlocked.Add(ref foundfilesCount, hits); ProcessedFile(this, new ProgressStatus(false, processedFilesCount, foundfilesCount, fileSearchResults, file)); } archiveEngine.StartingFileSearch -= ArchiveEngine_StartingFileSearch; } else { Interlocked.Increment(ref processedFilesCount); var fileSearchResults = engine.Search(file, searchPattern, searchType, searchOptions, encoding).ToList(); if (fileSearchResults != null && fileSearchResults.Count > 0) { AddSearchResults(fileSearchResults); } int hits = fileSearchResults.Where(r => r.IsSuccess).Count(); Interlocked.Add(ref foundfilesCount, hits); ProcessedFile(this, new ProgressStatus(false, processedFilesCount, foundfilesCount, fileSearchResults, file)); } GrepEngineFactory.ReturnToPool(file, engine); } catch (Exception ex) { logger.Error(ex, "Failed in Search"); AddSearchResult(new GrepSearchResult(file, searchPattern, ex.Message, false)); if (ProcessedFile != null) { List <GrepSearchResult> _results = new List <GrepSearchResult> { new GrepSearchResult(file, searchPattern, ex.Message, false) }; ProcessedFile(this, new ProgressStatus(false, processedFilesCount, foundfilesCount, _results, file)); } } finally { if (searchOptions.HasFlag(GrepSearchOption.StopAfterFirstMatch) && searchResults.Count > 0) { if (cancellationTokenSource != null) { cancellationTokenSource.Cancel(); } } } }
/// <summary> /// Searches folder for files whose content matches regex /// </summary> /// <param name="files">Files to search in. If one of the files does not exist or is open, it is skipped.</param> /// <param name="searchRegex">Regex pattern</param> /// <returns>List of results. If nothing is found returns empty list</returns> public List <GrepSearchResult> Search(IEnumerable <string> files, SearchType searchType, string searchPattern, GrepSearchOption searchOptions, int codePage) { searchResults.Clear(); if (files == null) { return(searchResults); } if (string.IsNullOrEmpty(searchPattern)) { return(searchResults); } Utils.CancelSearch = false; processedFilesCount = 0; foundfilesCount = 0; try { if (SearchParams.SearchParallel) { cancellationTokenSource = new CancellationTokenSource(); ParallelOptions po = new ParallelOptions { MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount * 4 / 5), CancellationToken = cancellationTokenSource.Token }; Parallel.ForEach(files, po, f => Search(f, searchType, searchPattern, searchOptions, codePage)); } else { foreach (var file in files) { Search(file, searchType, searchPattern, searchOptions, codePage); if (searchOptions.HasFlag(GrepSearchOption.StopAfterFirstMatch) && searchResults.Count > 0) { break; } if (Utils.CancelSearch) { break; } } } } catch (OperationCanceledException) { // expected for stop after first match or user cancel } catch (Exception ex) { logger.Error(ex, "Failed in search in files"); } finally { if (cancellationTokenSource != null) { cancellationTokenSource.Dispose(); cancellationTokenSource = null; } GrepEngineFactory.UnloadEngines(); } return(new List <GrepSearchResult>(searchResults)); }
protected string DoRegexReplace(int lineNumber, int filePosition, string text, string searchPattern, string replacePattern, GrepSearchOption searchOptions, IEnumerable <GrepMatch> replaceItems) { RegexOptions regexOptions = RegexOptions.None; if (!searchOptions.HasFlag(GrepSearchOption.CaseSensitive)) { regexOptions |= RegexOptions.IgnoreCase; } if (searchOptions.HasFlag(GrepSearchOption.Multiline)) { regexOptions |= RegexOptions.Multiline; } if (searchOptions.HasFlag(GrepSearchOption.SingleLine)) { regexOptions |= RegexOptions.Singleline; } bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); if (isWholeWord) { if (!searchPattern.Trim().StartsWith("\\b")) { searchPattern = "\\b" + searchPattern.Trim(); } if (!searchPattern.Trim().EndsWith("\\b")) { searchPattern = searchPattern.Trim() + "\\b"; } } // Issue #210 .net regex will only match the $ end of line token with a \n, not \r\n or \r bool convertToWindowsNewline = false; string searchPatternForReplace = searchPattern; if (searchPattern.Contains("$") && text.Contains("\r\n")) { convertToWindowsNewline = true; searchPatternForReplace = searchPattern.Replace("\r\n", "\n"); replacePattern = replacePattern.Replace("\r\n", "\n"); } StringBuilder sb = new StringBuilder(); int counter = 0; foreach (GrepMatch match in RegexSearchIterator(lineNumber, filePosition, text, searchPattern, searchOptions)) { if (replaceItems.Any(r => match.Equals(r) && r.ReplaceMatch)) { string matchText = text.Substring(match.StartLocation - filePosition, match.Length); int matchTextLength = matchText.Length; // save in case the newline is changed if (convertToWindowsNewline) { matchText = matchText.Replace("\r\n", "\n"); } string replaceText = Regex.Replace(matchText, searchPatternForReplace, DoPatternReplacement(matchText, replacePattern), regexOptions); if (convertToWindowsNewline) { replaceText = replaceText.Replace("\n", "\r\n"); } sb.Append(text.Substring(counter, match.StartLocation - filePosition - counter)); sb.Append(replaceText); counter = match.StartLocation - filePosition + matchTextLength; } if (Utils.CancelSearch) { break; } } sb.Append(text.Substring(counter)); string result = sb.ToString(); return(result); }
/// <summary> /// Searches folder for files whose content matches regex /// </summary> /// <param name="files">Files to search in. If one of the files does not exist or is open, it is skipped.</param> /// <param name="searchRegex">Regex pattern</param> /// <returns>List of results. If nothing is found returns empty list</returns> public List <GrepSearchResult> Search(IEnumerable <string> files, SearchType searchType, string searchPattern, GrepSearchOption searchOptions, int codePage) { searchResults.Clear(); if (files == null) { return(searchResults); } Utils.CancelSearch = false; if (searchPattern == null || searchPattern.Trim() == "") { int count = 0; foreach (string file in files) { count++; ProcessedFile(this, new ProgressStatus(true, searchResults.Count, count, null, file)); searchResults.Add(new GrepSearchResult(file, searchPattern, null, Encoding.Default)); if ((searchOptions & GrepSearchOption.StopAfterFirstMatch) == GrepSearchOption.StopAfterFirstMatch) { break; } if (Utils.CancelSearch) { break; } } ProcessedFile(this, new ProgressStatus(false, searchResults.Count, count, searchResults, null)); return(new List <GrepSearchResult>(searchResults)); } else { processedFilesCount = 0; foundfilesCount = 0; try { if (SearchParams.SearchParallel) { cancellationTokenSource = new CancellationTokenSource(); ParallelOptions po = new ParallelOptions(); po.MaxDegreeOfParallelism = Environment.ProcessorCount * 4 / 5; po.CancellationToken = cancellationTokenSource.Token; Parallel.ForEach(files, po, f => Search(f, searchType, searchPattern, searchOptions, codePage)); } else { foreach (var file in files) { Search(file, searchType, searchPattern, searchOptions, codePage); if (searchOptions.HasFlag(GrepSearchOption.StopAfterFirstMatch) && searchResults.Count > 0) { break; } } } } catch (OperationCanceledException) { // expected for stop after first match or user cancel } catch (Exception ex) { logger.Error(ex, "Failed in search in files"); } finally { if (cancellationTokenSource != null) { cancellationTokenSource.Dispose(); cancellationTokenSource = null; } GrepEngineFactory.UnloadEngines(); } return(new List <GrepSearchResult>(searchResults)); } }
private IEnumerable <GrepMatch> RegexSearchIterator(int lineNumber, int filePosition, string text, string searchPattern, GrepSearchOption searchOptions) { RegexOptions regexOptions = RegexOptions.None; if (!searchOptions.HasFlag(GrepSearchOption.CaseSensitive)) { regexOptions |= RegexOptions.IgnoreCase; } if (searchOptions.HasFlag(GrepSearchOption.Multiline)) { regexOptions |= RegexOptions.Multiline; } if (searchOptions.HasFlag(GrepSearchOption.SingleLine)) { regexOptions |= RegexOptions.Singleline; } bool isWholeWord = searchOptions.HasFlag(GrepSearchOption.WholeWord); if (isWholeWord) { if (!searchPattern.Trim().StartsWith("\\b")) { searchPattern = "\\b" + searchPattern.Trim(); } if (!searchPattern.Trim().EndsWith("\\b")) { searchPattern = searchPattern.Trim() + "\\b"; } } // Issue #210 .net regex will only match the $ end of line token with a \n, not \r\n or \r // see https://msdn.microsoft.com/en-us/library/yd1hzczs.aspx#Multiline // and http://stackoverflow.com/questions/8618557/why-doesnt-in-net-multiline-regular-expressions-match-crlf // must change the Windows and Mac line ends to just the Unix \n char before calling Regex if (searchPattern.Contains("$")) { // if the search pattern has Windows or Mac newlines, they must be converted, too searchPattern = searchPattern.Replace("\r\n", "\n"); searchPattern = searchPattern.Replace('\r', '\n'); if (lineNumber == -1 && text.Contains("\r\n")) { foreach (var match in RegexSearchIteratorSpecial(text, searchPattern, regexOptions)) { yield return(match); } yield break; } if (text.Contains("\r\n")) { text = text.Replace("\r\n", "\n"); } else if (text.Contains("\r")) { text = text.Replace('\r', '\n'); } } var lineEndIndexes = GetLineEndIndexes((initParams.VerboseMatchCount && lineNumber == -1) ? text : null); List <GrepMatch> globalMatches = new List <GrepMatch>(); var matches = Regex.Matches(text, searchPattern, regexOptions, MatchTimeout); foreach (Match match in matches) { if (initParams.VerboseMatchCount && lineEndIndexes.Count > 0) { lineNumber = lineEndIndexes.FindIndex(i => i > match.Index) + 1; } yield return(new GrepMatch(lineNumber, match.Index + filePosition, match.Length)); } }