Select-String: соответствует строке, только если ей не предшествует определенный символ - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть список файлов, которые содержат одну из двух строк:

"stuff" или ";stuff"

Я пытаюсь написать сценарий PowerShell, которыйвернет только те файлы, которые содержат "stuff".Сценарий, приведенный ниже, в настоящее время возвращает все файлов, потому что, очевидно, "stuff" является подстрокой ";stuff"

Насколько я понимаю, я не могу понять, как сопоставлять только совпаденияфайл, содержащий "stuff", без предшествующего ;

Get-Content "C:\temp\list\list.txt" |
  Where-Object { Select-String -Quiet -Pattern "stuff" -SimpleMatch $_ }

Примечание: C:\temp\list\list.txt содержит список путей к файлам, каждый из которых передается в Select-String.

Спасибо за помощь.

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

В дополнение к ответу @ mklement0, я предлагаю альтернативный подход для облегчения чтения и понимания вашего кода:

#requires -Version 4
@(Get-Content -Path 'C:\Temp\list\list.txt').
    ForEach([IO.FileInfo]).
    Where({ $PSItem | Select-String -Pattern '(?<!;)stuff' -Quiet })

Это превратит ваши строки в объекты (System.IO.FilePath) и использует функции массиваForEach и Where для краткости / краткости.Кроме того, это позволяет вам направлять пути как объекты , которые будут приняты параметром -Path в Select-String, чтобы сделать его более понятным (я нахожу длинные списки наборов параметров трудными для чтения).

0 голосов
/ 01 марта 2019

Невозможно выполнить желаемое сопоставление при поиске подстроки literal (-SimpleMatch).

Вместо этого используйте регулярное выражение с отрицательное косвенное утверждение ((?<!..)) для исключения stuff подстрок, перед которыми стоит ; char .: (?<!;)stuff

Применимо к вашей команде:

Get-Content "C:\temp\list\list.txt" | 
  Where-Object { Select-String -Quiet -Pattern '(?<!;)stuff' -LiteralPath $_ }

Подводные камни Regex:

  • Заманчиво использовать вместо этого [^;]stuff, используя с отрицанием (^)набор символов ([...]) (см. этот ответ );однако, не будет работать должным образом, если stuff появится в самом начале строки , поскольку набор символов - независимо от того, отменен он или нет - соответствует только фактическому символ , а не начало строки позиция .

  • Затем возникает соблазн применить ? к отрицательному набору символов (для опционально совпадение - 0 или 1 вхождение): [^;]?stuff.Однако это будет соответствовать строке, содержащей ;stuff снова, учитывая, что stuff является технически , которому предшествует "0-повторное вхождение" отрицательного набора символов;таким образом, ';stuff' -match '[^;]?stuff' приводит к $true.

В этом случае правильно работает только ретроспективное утверждение - см. регулярные-выражения.info .

0 голосов
/ 28 февраля 2019

Приведенный пример кода на самом деле не будет работать, так как он будет рассматривать каждую строку как значение -Path.

Вам нужно получить содержимое, выберите строку, которую вы ищете,затем отфильтруйте результаты с помощью Where-Object

Get-Content "C:\temp\list\list.txt" | Select-String -Pattern "stuff" | Where-Object {$_ -notmatch ";stuff"}

При необходимости вы можете создать более сложное регулярное выражение, но это зависит от того, как ваши данные результатов из ваших файлов выглядят

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...