У меня есть строка в Bash:
string="My string"
Как я могу проверить, содержит ли она другую строку?
if [ $string ?? 'foo' ]; then
echo "It's there!"
fi
Где ??
мой неизвестный оператор. Я использую эхо и grep
?
if echo "$string" | grep 'foo'; then
echo "It's there!"
fi
Это выглядит немного неуклюже.
expr
команду здесьОтветы:
Вы также можете использовать ответ Маркуса (* подстановочные знаки) вне оператора case, если вы используете двойные скобки:
Обратите внимание, что пробелы в строке иглы должны быть помещены между двойными кавычками, а
*
подстановочные знаки должны быть снаружи. Также обратите внимание, что используется простой оператор сравнения (т.е.==
), а не оператор регулярного выражения=~
.источник
#!/bin/sh
. Попробуй#!/bin/bash
вместо этого.[[
. Смотрите ideone.com/ZSy1gZЕсли вы предпочитаете подход регулярных выражений:
источник
=~
Оператор уже ищет всю строку на матч; что.*
«s здесь посторонний. Кроме того, кавычки, как правило, предпочтительнее обратной косой черты:[[ $string =~ "My s" ]]
E14)
. Вероятно, лучше присвоить переменную (используя кавычки), а затем сравнить. Как это:re="My s"; if [[ $string =~ $re ]]
if [[ ! "abc" =~ "d" ]]
верно.number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;
Я не уверен в использовании оператора if, но вы можете получить аналогичный эффект с помощью оператора case:
источник
[[ $string == *foo* ]]
также работает в некоторых POSIX-совместимых версиях sh (например,/usr/xpg4/bin/sh
в Solaris 10) и ksh (> = 88)[[
... переключатель корпуса работал!stringContain
варианты (совместимые или независимые от регистра)Поскольку эти ответы о переполнении стека говорят в основном о Bash , я опубликовал независимый случай функцию Bash в самом конце этого поста ...
Во всяком случае, есть мой
Совместимый ответ
Поскольку уже есть много ответов, использующих специфичные для Bash функции, есть способ работать с более слабыми оболочками, такими как BusyBox :
На практике это может дать:
Это было проверено в Bash, Dash , KornShell (
ksh
) и ash (BusyBox), и результат всегда:В одну функцию
По словам @EeroAaltonen, вот версия того же демо, протестированная под теми же оболочками:
Затем:
Обратите внимание: вы должны экранировать или заключить в двойные кавычки и / или двойные кавычки:
Простая функция
Это было протестировано под BusyBox, Dash и, конечно же, Bash:
То теперь:
... Или если отправленная строка может быть пустой, как указано @Sjlver, функция станет такой:
или как предложено в комментарии Адриана Гюнтера , избегая
-o
переключателей:Финальная (простая) функция:
И инвертировать тесты, чтобы сделать их потенциально быстрее:
С пустыми строками:
Независимо от регистра (только Bash!)
Для тестирования строк без учета регистра просто конвертируйте каждую строку в нижний регистр:
Проверьте:
источник
string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; }
заключительной мыслью: содержит ли пустая строка пустую строку? Версия выше вещи да (из-за-o -z "$1"
части).Вы должны помнить, что сценарии оболочки - это не столько язык, сколько набор команд. Инстинктивно вы думаете, что этот «язык» требует, чтобы вы следовали
if
с a[
или a[[
. Обе они являются просто командами, которые возвращают состояние выхода, указывающее на успех или неудачу (как и любая другая команда). По этой причине я бы использовалgrep
, а не[
команду.Просто делать:
Теперь, когда вы рассматриваете
if
тестирование состояния завершения команды, которая следует за ней (завершается точкой с запятой), почему бы не пересмотреть источник строки, которую вы тестируете?-q
Опция делает Grep не выводить ничего, как мы только хотим , код возврата.<<<
заставляет оболочку развернуть следующее слово и использовать его в качестве входных данных для команды, однострочной версии<<
документа здесь (я не уверен, является ли это стандартным или Bashism).источник
if grep -q foo <(echo somefoothing); then
echo
это непереносимо, если вы передаете переменную, используйтеprintf '%s' "$string
вместо этого.grep -q foo <<<"$mystring"
высока : выполнение 1 вилки, это башизм иecho $mystring | grep -q foo
2 вилки (одна для трубы, а вторая для бега/path/to/grep
)echo
без флагов может по-прежнему иметь непредвиденные проблемы с переносимостью, если строка аргумента содержит последовательности с обратной косой чертой.echo "nope\c"
ожидается, что на некоторых платформах будет работать какecho -e "nope"
на некоторых других.printf '%s' "nope"
противprintf '%s\n' 'nope\c'
Принятый ответ лучше, но, поскольку есть несколько способов сделать это, вот другое решение:
${var/search/replace}
это$var
с первым экземпляромsearch
замененоreplace
, если он найден (это не меняет$var
). Если вы попытаетесь заменитьfoo
ничем, а строка изменилась, то, очевидно,foo
был найден.источник
Так что есть много полезных решений вопроса - но какой из них самый быстрый / использует наименьшее количество ресурсов?
Повторные тесты с использованием этого кадра:
Замена TEST каждый раз:
(doContain был в ответе Ф. Хури)
И для хихиканья:
Таким образом, опция простого замещения предсказуемо выигрывает либо в расширенном тесте, либо в случае. Чехол переносной.
Выпадение до 100000 greps предсказуемо больно! Старое правило об использовании внешних утилит без необходимости сохраняется.
источник
[[ $b == *$a* ]]
.case
выигрывает с наименьшим общим временем. Вы пропустили звездочку после того,$b in *$a
как. Я получаю немного более быстрые результаты,[[ $b == *$a* ]]
чем заcase
исправленную ошибку, но, конечно, это может зависеть и от других факторов.[[ $b == *$a* ]]
быстрый иcase
почти такой же быстрый (и приятно POSIX-совместимый).Это также работает:
И отрицательный тест это:
Я полагаю, что этот стиль немного более классический - меньше зависит от особенностей оболочки Bash.
--
Аргумент чисто POSIX паранойя, используется для защищенных от входных строк , подобных опции, таких как--abc
или-a
.Примечание. В узком цикле этот код будет работать намного медленнее, чем при использовании внутренних функций оболочки Bash, поскольку один (или два) отдельных процесса будут создаваться и соединяться через каналы.
источник
echo
является непереносимым, вы должны использоватьprintf '%s' "$haystack
вместо этого.echo
всего, кроме буквального текста без escape-символов, которые не начинаются с a-
. Это может работать для вас, но это не портативно. Даже bashecho
будет вести себя по-разному в зависимости от того, установлена лиxpg_echo
опция. PS: я забыл закрыть двойную кавычку в моем предыдущем комментарии.--
не указан в спецификации POSIX дляprintf
, но вы должны использовать вprintf '%s' "$anything"
любом случае, чтобы избежать проблем, если$anything
содержит%
символ.Bash 4+ примеров. Примечание: неиспользование кавычек приведет к проблемам, когда слова содержат пробелы и т. Д. Всегда заключайте в Bash, IMO.
Вот несколько примеров Bash 4+:
Пример 1, проверьте «да» в строке (без учета регистра):
Пример 2, проверьте «да» в строке (без учета регистра):
Пример 3, проверьте «да» в строке (с учетом регистра):
Пример 4, проверьте «да» в строке (с учетом регистра):
Пример 5, точное совпадение (с учетом регистра):
Пример 6, точное совпадение (без учета регистра):
Пример 7, точное совпадение:
Пример 8, подстановочный знак .ext (без учета регистра):
Наслаждаться.
источник
Как насчет этого:
источник
Как Павел упоминал в своем сравнении производительности:
Это соответствует POSIX, как 'case' $ string 'в' ответе, предоставленном Маркусом , но его немного легче прочитать, чем ответ оператора case. Также обратите внимание, что это будет намного медленнее, чем использование оператора case. Как указывал Пол, не используйте это в цикле.
источник
Этот ответ переполнения стека был единственным, кто ловил пробел и тире символов:
источник
источник
echo "Couldn't find
оператор в конце является хорошим трюком для возврата 0 состояний выхода для этих соответствующих команд.|| echo "Couldn't find"
вы вернете состояние выхода из ошибки, если не будет совпадения, чего вы, возможно, не захотите, если вы запускаете конвейер CI, например, где вы хотите, чтобы все команды возвращались статусы выхода без ошибокОдин:
источник
expr
это одна из тех утилит для швейцарских армейских ножей, которые обычно могут делать все, что вам нужно, как только вы поймете, как это сделать, но после внедрения вы никогда не сможете вспомнить, почему или как он делает то, что делает, так что вы никогда не трогай его снова и надейся, что он никогда не перестанет делать то, что делает.expr
, в редких случаях, когда переносимость не позволяет использовать bash (например, несовместимое поведение в более старых версиях), tr (несовместимый везде) или sed (иногда слишком медленный). Но из личного опыта, когда бы я ни перечитывал этиexpr
-измы, я должен вернуться на страницу руководства. Итак, я бы просто прокомментировал, что каждое использованиеexpr
будет прокомментировано ...expr
иtest
были реализованы для их выполнения. В наше время обычно существуют лучшие инструменты, многие из которых встроены в любую современную оболочку. Я думаю,test
что все еще там висит, но, кажется, никто не пропалexpr
.Мне нравится Сед.
Редактировать, Логика:
Используйте sed, чтобы удалить экземпляр подстроки из строки
Если новая строка отличается от старой, существует подстрока
источник
grep -q
полезно для этого.То же самое с использованием
awk
:Вывод:
Вывод:
Первоисточник: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html
источник
echo
является непереносимым, вы должны использоватьprintf '%s' "$string"
вместо этого. Я редактирую ответ, потому что пользователь, кажется, больше не существует.echo
Каким образом не является портативным, @ nyuszika7h?Я обнаружил, что эта функциональность нужна довольно часто, поэтому я использую самодельную функцию оболочки в своем
.bashrc
подобии, которая позволяет мне использовать ее так часто, как мне нужно, с легко запоминающимся именем:Чтобы проверить
$string1
, содержится ли (скажем, abc ) в$string2
(скажем, 123abcABC ), мне просто нужно запуститьstringinstring "$string1" "$string2"
и проверить, например, возвращаемое значениеисточник
x
взлом требуется только для очень старых оболочек.Мой .bash_profile файл и как я использовал grep:
Если переменная окружения PATH включает мои две
bin
директории, не добавляйте их,источник
grep -q -E 'pattern1|...|patternN'
.Расширение вопроса, на который здесь дан ответ Как узнать, содержит ли строка другую строку в POSIX sh? :
Это решение работает со специальными символами:
источник
contains "-n" "n"
здесь не работает, потомуecho -n
что проглотит-n
как опцию!printf "%s\n" "$string"
Вместо этого популярным решением является использование .Поскольку вопрос POSIX / BusyBox закрыт без предоставления правильного ответа (IMHO), я выложу ответ здесь.
Кратчайший возможный ответ:
или
Обратите внимание , что двойной хэш является обязательным с некоторыми оболочками (
ash
). Выше будет оцениваться,[ stringvalue ]
когда подстрока не найдена. Это не возвращает ошибку. Когда подстрока найдена, результат является пустым, и он оценивает[ ]
. Это выдаст код ошибки 1, так как строка полностью заменена (из-за*
).Самый короткий более распространенный синтаксис:
или
Другой:
или
Обратите внимание на один знак равенства!
источник
Точное совпадение слов:
источник
Попробуйте ообаш.
Это библиотека строк в стиле OO для Bash 4. Она поддерживает немецкие умлауты. Это написано на Bash.
Многие функции:
-base64Decode
,-base64Encode
,-capitalize
,-center
,-charAt
,-concat
,-contains
,-count
,-endsWith
,-equals
,-equalsIgnoreCase
,-reverse
,-hashCode
,-indexOf
,-isAlnum
,-isAlpha
,-isAscii
,-isDigit
,-isEmpty
,-isHexDigit
,-isLowerCase
,-isSpace
,-isPrintable
,-isUpperCase
,-isVisible
,-lastIndexOf
,-length
,-matches
,-replaceAll
,-replaceFirst
,-startsWith
,-substring
,-swapCase
,-toLowerCase
,-toString
,-toUpperCase
,-trim
, и-zfill
.Посмотрите на содержащийся пример:
oobash доступен на Sourceforge.net .
источник
Я использую эту функцию (одна зависимость не включена, но очевидна). Он проходит испытания, показанные ниже. Если функция возвращает значение> 0, то строка была найдена. Вы можете так же легко вернуть 1 или 0 вместо этого.
источник
Это тот же ответ, что и https://stackoverflow.com/a/229585/11267590 . Но простой стиль, а также POSIX-совместимость.
источник
Это найдет любое вхождение a или b или c
источник
Общий пример стога сена иглы следующий с переменными
источник