PowerShell и оператор -contains

143

Рассмотрим следующий фрагмент:

"12-18" -Contains "-"

Вы думаете, что это оценивает true, но это не так. Это оценит falseвместо. Я не уверен, почему это происходит, но это происходит.

Чтобы избежать этого, вы можете использовать это вместо:

"12-18".Contains("-")

Теперь выражение оценит как истинное.

Почему первый фрагмент кода ведет себя так? есть что-то особенное -, с чем не очень приятно играть -Contains? В документации ничего не говорится об этом.

ТЯО
источник

Ответы:

197

-ContainsОператор не делает подстроки сравнения и матч должен быть на полную строку и используется для поиска коллекций.

Из документации, на которую вы ссылаетесь:

-Содержит описание: оператор сдерживания. Сообщает, включает ли коллекция эталонных значений одно тестовое значение.

В приведенном вами примере вы работаете с коллекцией, содержащей только один строковый элемент.

Если вы прочитаете документацию, на которую вы ссылались, вы увидите пример, демонстрирующий это поведение:

Примеры:

PS C:\> "abc", "def" -Contains "def"
True

PS C:\> "Windows", "PowerShell" -Contains "Shell"
False  #Not an exact match

Я думаю, что вы хотите, это -Matchоператор:

"12-18" -Match "-"

Который возвращается True .

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

Кев
источник
14
Для полноты, хотя -Match может быть хорошим совпадением, он использует регулярные выражения. Если кто-то хочет, чтобы однозначная строка содержала проверку, следует сделать так, как описывает OP:"12-18".Contains("-")
8DH
4
@ 8DH - очень хороший улов :). Перечитав вопрос, я думаю, мне нужно прояснить разницу между Containsоператором powershell и методом .Contains() .NET String .
Кев
1
Как уже упоминалось в комментарии выше, -Matchиспользуется регулярное выражение. Это означает, что строковый параметр - это регулярное выражение, а не обычная строка. Например, "hello" -Match "."вернет true, потому что "."это регулярное выражение, где '.' будет соответствовать любому персонажу. Чтобы проверить, содержит ли строка точку остановки: "hello" -Match "\."(возвращает false)
malla
1
@malla - хороший момент, я редактировал заметку об этом. Спасибо.
Кев
Это, безусловно, «ложный друг»! :) Существование слова "-contains" означает "принадлежность к списку".
Рауль Салинас-Монтеагудо
38

-Containsна самом деле оператор коллекции. Это правда, если коллекция содержит объект. Он не ограничен строками.

-match и -imatch являются сопоставителями строк регулярных выражений и устанавливают автоматические переменные для использования с захватами.

-like, -ilikeЯвляются SQL-подобный matchers.

Эрис
источник
13

Вы можете использовать like:

"12-18" -like "*-*"

Или splitдля contains:

"12-18" -split "" -contains "-"
Esperento57
источник