Как заставить PowerShell `Select-String`, также известный как `sls`, выводить только точные совпадения?

В сценарии PowerShell я хотел бы проверить, существует ли уже локальная ветка, что я сейчас делаю как $existsInLocal = (git branch | sls $branch) -ne $null, но это неверно, потому что sls $branch соответствует строке(ям), содержащей $branch в качестве подстроки, но мне нужна версия sls $branch, который выводит строки, точно соответствующие $branch.

Есть ли способ использовать ^ и $ для обозначения начала и конца строки соответственно? Мои попытки сделать это не увенчались успехом.

Я просмотрел документацию Select-String и не нашел решения.

Здесь также есть почти решение , в котором используется \b, который соответствует границе слова, но в моем случае это не работает, поскольку имена ветвей могут содержать символы \W (например, / или -). Например, \bjose/feature\b будет соответствовать dev/jose/feature (первый \b соответствует переходу от / к j) или jose/feature/v2 или dev/jose/feature/v2.


Я знаю есть другой способ проверить существование локальной ветки, но меня больше всего интересуют sls точные совпадения в целом, и вариант использования «определить, существует ли локальная ветка» — лишь один из многих.

У меня это работает… $stdout = @( "main", "feature", "feature/abc", "feature/xyz" ); $stdout | select-string "^feature`$" — обратите внимание, что вам нужно экранировать $ в шаблоне ветки. Если у вас есть конкретный контрпример, который не работает, было бы полезно включить его в свой пост. (Кроме того, если вы просто ищете точную литеральную строку без шаблонов регулярных выражений, кроме ^…$, вы можете использовать -contains вместо select-string)

mclayton 26.07.2024 10:06
Select-String -SimpleMatch?
iRon 26.07.2024 10:09
echo there | select-string ^there$
js2010 26.07.2024 15:08

@mclayton, спасибо, ^ и $ действительно работают с sls/select-string. Моя проблема заключалась в том, что я не учитывал пробелы, которые git branch печатаются перед каждым названием ветки. У меня сработало следующее git branch | sls ^\s*dev/jose$ из командной строки и в .ps1 скрипте.

joseville 26.07.2024 15:44

Для меня @iRon использование -SimpleMatch вернуло больше, чем просто точные совпадения; он также вернул совпадения подстроки.

joseville 26.07.2024 15:45

@mclayton git branch --contains dev/jose выводит `dev/jose\n *master`, если я нахожусь в ветке master; * dev/jose\n master если я в dev/jose филиале; и `dev/jose\n master`, если я из любой другой ветки. Переменный вывод делает его неподходящим для сценариев. И git branch --contains dev/jos и git branch --contains dev/josev каждый выводит error: malformed object name dev/jos и error: ... dev/josev соответственно.

joseville 26.07.2024 15:52

Таким образом, строка выбора может соответствовать точному шаблону, вам просто нужно включить начальные пробелы.

js2010 26.07.2024 16:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
72
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Переписывание регулярного выражения может оказаться всем, что вам нужно. Следующее работает для случайной строки с косыми чертами и тире (спасибо mklement0 за указание на упрощение).

^[-/\w]+$

Некоторые объяснения:

  • []+ определяет список совпадающих символов, который может повторяться один или несколько раз
  • / соответствует косой черте
  • - соответствует тире
  • \w соответствует символам слова (вы это уже нашли)
  • ^ и $ будут соответствовать началу и концу строки (опять же, вы уже это выяснили)

Таким образом, внутренний захват в списке будет соответствовать любому словесному символу, косой черте или тире. Если вы повторите это один или несколько раз и включите начало и конец строки, это будет соответствовать описанному вами шаблону.

Спасибо за объяснение @mklement0. Я обновил свой ответ, чтобы показать вашу строку регулярного выражения на случай, если кто-то найдет этот вопрос в будущем.

TheBrickAdmin 28.07.2024 16:57
Ответ принят как подходящий

Чтобы ответить на ваш общий вопрос:

Меня действительно больше всего интересует, находит ли sls (Select-String) точные совпадения в целом.

  • Select-String по дизайну ищет заданный поисковый запрос в виде подстроки в каждой входной строке (строке).[1]

    • По умолчанию он также сопоставляется без учета регистра, что соответствует обычному регистронезависимому характеру PowerShell; при необходимости используйте переключатель -CaseSensitive.
  • По умолчанию каждый поисковый запрос, передаваемый в параметр -Pattern (возможно, позиционно, как первый безымянный аргумент), интерпретируется как регулярное выражение (регулярное выражение).

    • Чтобы искать подстроки буквально (дословно), добавьте переключатель -SimpleMatch.
  • Нет возможности запросить совпадение всей строки, поэтому единственный способ добиться соответствия всей строки — это использовать регулярное выражение с привязками ^ и $ .

    • Однако для этого может потребоваться экранирование поискового термина, предназначенного для буквального использования, чтобы любые символы, являющиеся метасимволами регулярного выражения, не были случайно интерпретированы как таковые.

    • Используйте [regex]::Escape(), чтобы выполнить это экранирование программно; в буквальном поисковом запросе вы можете альтернативно \-экранировать метасимволы по отдельности.

  • По умолчанию Select-String ищет все совпадения во входном файле/среди входных строк.

    • Чтобы он сообщал только о первом совпадении и прекратил поиск дополнительных, добавьте переключатель -List, но учтите, что это работает только с вводом файла (либо через -Path/-LiteralPath, либо путем передачи объектов информации о файле через Get-ChildItem или Get-Item).

    • Чтобы он сообщал только логическое значение ($true или $false) в зависимости от того, было ли найдено хотя бы одно совпадение (что также прекращает поиск после первого совпадения), вместо этого добавьте переключатель -Quiet.

      • Примечание. При передаче строк в Select-String и совпадении не найдено, начиная с PowerShell 7.4.x, вместо $false неожиданно отсутствует вывод; это следует считать ошибкой — см. выпуск GitHub № 16681.
        Однако приведение этого отсутствия вывода к логическому значению, например в операторе if эквивалентен $false, поэтому эта ошибка обычно не имеет значения.
    • Кроме того, независимо от -List, переключатель -AllMatches требует, чтобы поисковый запрос сопоставлялся так часто, как он встречается в каждой строке (входной строке), а не сообщал только о первом совпадении.


Применительно к вашему случаю:

$existsInLocal = git branch | sls -Quiet ('^\s*{0}$' -f [regex]::Escape($branch))
  • Вышеприведенное демонстрирует технику экранирования, хотя в вашем случае это, вероятно, не обязательно, и, согласно вашему отзыву, соответствует \s*, то есть необязательным пробелам перед именем ветки.

  • -Quiet делает Select-String вывод $true, если совпадение было найдено (см. выше), а также прекращает поиск в этом случае - это устраняет необходимость в вашем (...) -ne $null тесте, который, кстати, обычно лучше записать как $null -ne (...) - см. соответствующее правило PSScriptAnalzyer


Делаем шаг назад:

Как отмечает Маклейтон , возможно более простое решение для буквального сопоставления целых строк с использованием оператора -contains:

$existsInLocal = (git branch) -contains $branch
  • PowerShell автоматически передает выходные данные стандартной программы внешней программы построчно и, заключая вызов в (...) и используя его с оператором, строки собираются в массив (при условии наличия двух или более строк вывода).

  • -contains затем выполняет поэлементное сравнение на равенство в этом массиве (по сути, -eq операции с каждым элементом массива в качестве LHS) до тех пор, пока не будет найдено совпадение (не более одного), и в этом случае возвращается $true (в противном случае $false). В данном случае это означает буквальное сравнение целых строк.

    • Примечание. -contains по умолчанию тоже нечувствителен к регистру, но вы можете использовать вариант оператора с учетом регистра -ccontains.

Единственным потенциальным недостатком этого подхода является то, что он требует сбора всех строк стандартного вывода в памяти заранее, прежде чем будет выполнено сопоставление, тогда как потоковая природа конвейерного решения на основе Select-String позволяет остановиться, как только будет найдено совпадение.
Однако при ограниченном объеме вывода стандартного вывода, как в данном случае, это не будет проблемой.


[1] The typical use case is that Select-String receives text line by line, such as by making it search a file using -Path / -LiteralPath or when piping the output of an external program to it.
However, when you pass a multiline string as a single object to it (e.g. by piping Get-Content -Raw to it), that string is searched through as a whole, enabling cross-line matching.

Другие вопросы по теме