param ( [string]$SearchDir = "C:\Users", [string]$PathFilter = "yandex", [string]$Words = "name folder path", [int]$TotalLen = 50 # Общая длина вывода (например, 50) ) [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 $keywordsRegex = $Words.Replace(" ", "|") $excludePattern = "Extensions|IndexedDB|leveldb|Cache|component|Updater" # Фиксированное смещение влево $offsetL = 10 Write-Host "=== OFFSET SEARCH STARTED ===" -ForegroundColor Cyan Write-Host "Target: $SearchDir | Total Length: $TotalLen | Left: $offsetL / Right: $($TotalLen - $offsetL)" Write-Host "--------------------------------------------------" $script:foundCount = 0 function Get-FilesSafely { param ($CurrentPath) try { $items = Get-ChildItem -Path $CurrentPath -Force -ErrorAction SilentlyContinue foreach ($item in $items) { if (-not $item.PSIsContainer) { $fName = $item.FullName # Фильтр расширений и пути if ($fName -match '\.(xml|json|conf|ini|js|lic|properties|cfg)$' -and $fName -ilike "*$PathFilter*" -and $fName -notmatch $excludePattern) { # Читаем содержимое файла с принудительной кодировкой UTF8 $content = Get-Content -Raw -Path $fName -Encoding UTF8 -ErrorAction SilentlyContinue if ($null -eq $content) { continue } # Поиск всех вхождений слов $matches = [regex]::Matches($content, "(?i)$keywordsRegex") if ($matches.Count -gt 0) { Write-Host "`n[FILE]: $fName" -ForegroundColor Yellow $script:foundCount++ $lastEndIndex = -1 foreach ($m in $matches) { # Пропускаем, если текущее слово перекрывается предыдущим окном вывода if ($m.Index -lt $lastEndIndex) { continue } # Вычисляем начало: индекс слова МИНУС 10 $start = [Math]::Max(0, $m.Index - $offsetL) # Вычисляем длину: берем TotalLen, но не больше остатка файла $len = [Math]::Min($content.Length - $start, $TotalLen) # Извлекаем фрагмент и чистим от переносов строк $fragment = $content.Substring($start, $len).Replace("`n", " ").Replace("`r", " ") # Ищем слово внутри фрагмента для покраски # (Ищем с учетом того, что оно начинается через 10 символов от старта фрагмента) $localMatch = [regex]::Match($fragment, "(?i)$keywordsRegex") if ($localMatch.Success) { $prefix = $fragment.Substring(0, $localMatch.Index) $foundWord = $localMatch.Value $suffix = $fragment.Substring($localMatch.Index + $localMatch.Length) Write-Host " --- " -NoNewline -ForegroundColor Gray Write-Host $prefix -NoNewline Write-Host $foundWord -ForegroundColor Green -NoNewline Write-Host $suffix } # Запоминаем, где закончился этот фрагмент $lastEndIndex = $start + $len # Ограничение на количество находок в одном файле (чтобы не утонуть в логах) if ($script:foundCount -gt 1000) { break } } } } } } # Рекурсия по папкам foreach ($item in $items) { if ($item.PSIsContainer -and $item.Attributes -notlike "*ReparsePoint*") { Get-FilesSafely -CurrentPath $item.FullName } } } catch { } } Get-FilesSafely -CurrentPath $SearchDir Write-Host "`n--------------------------------------------------" Write-Host "=== SEARCH FINISHED ===" -ForegroundColor Cyan Write-Host "Files with matches: $script:foundCount"