Ответ AdminOfThing полезен, но я обнаружил, что хочу, чтобы вещи были оформлены по-другому.
Вы ищете способ выполнить поиск литералов по подстроке , который привязан в начале , который является косвенно поддерживается в PowerShell - решения см. В следующем разделе.
Операторы -contains
и -in
не связаны с подстрокой , совпадают (несмотря на сходство имен между -contains
и String.Contains()
.NET метод).
Они проверяют членство одного значения (содержится в целом ) в коллекции , поэлементно равенство сравнения (подразумевается -eq
). Подробнее см. документы и нижний раздел этого ответа .
Если вы хотите объединить две задачи - поиск подстроки во всех элементах коллекции - вы можете воспользоваться тем, что операторы PowerShell -match
и -like
- обсуждается ниже - может работать и на коллекциях -значных LHS, и в этом случае они действуют как фильтры ; хотя это не совсем то же самое, что тестирование на членство, оно может эффективно использоваться для этого; этот ответ показывает, как использовать -match
таким образом.
Решения:
Использование .NET Framework:
.NET String.IndexOf()
выполняет поиск литеральной подстроки и возвращает индекс на основе 0
символа, с которого начинается подстрока во входной строке (и -1
если подстрока вообще не может быть найдена):
PS> 0 -eq 'foo\bar'.IndexOf('foo\')
True
Обратите внимание, что, в отличие от операторов PowerShell, выше по умолчанию учитывается регистр по умолчанию, но вы можете перейти к режиму без учета регистра с дополнительными аргументами:
PS> 0 -eq 'foo\bar'.IndexOf('FOO\', [System.StringComparison]::InvariantCultureIgnoreCase)
True
Обратите внимание, что PowerShell использует инвариант , а не текущую культуру во многих (но не во всех) контекстах, таких как операторы -eq
, -contains
, -in
и оператор switch
.
Если вам не нужно было привязывать ваш поиск по подстроке, т. Е. Если вы хотите узнать только, содержится ли подстрока где-то во входной строке, вы можете использовать String.Contains()
PS> 'foo\bar'.Contains('oo\') #'# substring is present, but not at the start
True
Приведенные выше замечания о чувствительности к регистру применимы и здесь.
Использование оператора -match
:
Хотя -match
неявно выполняет сопоставление подстроки , оно основано на регулярном выражении ( регулярное выражение ), а не на буквальной строке.
-match
выполняет регистр- нечувствительный сопоставление по умолчанию; используйте вариант -cmatch
для чувствительности к регистру.
Это означает, что вы можете удобно использовать ^
, привязку начала ввода, чтобы гарантировать, что выражение поиска совпадает только с start входной строки.
И наоборот, для того, чтобы ваша строка поиска рассматривалась как литерал строка в вашем регулярном выражении, вы должны \
-экранировать любое регулярное выражение метасимволы (символы, которые имеют особое значение) в регулярном выражении.
Поскольку \
, следовательно, сам является метасимволом, его также следует экранировать, а именно как \\
.
В строковых литералах вы можете сделать экранирование вручную:
# Manual escaping: \ is doubled.
# Note the ^ to anchor matching at the start.
PS> 'foo\bar' -match '^foo\\'
True
Программно, когда строка является переменной, вы должны использовать метод [regex]::Escape()
:
# Programmatic escaping via [regex]::Escape()
# Note the ^ to anchor matching at the start.
PS> $s = 'foo\'; 'foo\bar' -match ('^' + [regex]::Escape($s))
True
Использование оператора -like
:
В отличие от -match
, -like
выполняет сопоставление полной строки и делает это на основе шаблонных выражений (он же globs в мире Unix); хотя они отдаленно связаны с регулярными выражениями, они используют более простой несовместимый синтаксис (и гораздо менее эффективны).
-like
выполняет регистр- нечувствительный сопоставление по умолчанию; используйте вариант -clike
для учета регистра.
Символы подстановки имеют только 3 основных конструкции и, следовательно, только 3 метасимволы: ?
(для сопоставления с одним символом), *
(для сопоставления с любым количеством символов., Включая отсутствие) и [
(начало набора символов или диапазона, соответствующих одному символу, например, [a-z]
или [45]
).
В простейшем случае вы можете просто добавить *
к строке поиска, чтобы увидеть, соответствует ли она в начале входной строки:
# OK, because 'foo\' contains none of: ? * [
PS> 'foo\bar' -like 'foo\*'
True
# With a variable, using an expandable string:
PS> $s = 'foo\'; 'foo\bar' -like "$s*"
True
Однако, как и в случае -match
, может потребоваться программное экранирование, которое требует вызова [WildcardPattern]::Escape()
:
PS> $s = 'foo['; 'foo[bar' -like ([WildcardPattern]::Escape($s) + '*')
True