Как проверить, содержит ли строка подстроку в Bash

avatar
davidsheldon
23 октября 2008 в 12:37
2456362
28
2971

У меня есть строка в Bash:

string="My string"

Как я могу проверить, содержит ли он другую строку?

if [ $string ?? 'foo' ]; then
  echo "It's there!"
fi

Где ?? - мой неизвестный оператор. Могу ли я использовать echo и grep?

if echo "$string" | grep 'foo'; then
  echo "It's there!"
fi

Выглядит немного неуклюже.

Источник
ericson.cepeda
5 мая 2015 в 06:14
4

Привет, если пустые строки неверны, почему вы считаете это неуклюжим? Это был единственный способ, который у меня сработал, несмотря на предложенные решения.

cifer
2 марта 2016 в 03:08
1

Здесь вы можете использовать команду expr

sehe
8 апреля 2016 в 15:31
4

Вот один для оболочек posix: coderhelper.com/questions/2829613/…

Ответы (28)

avatar
Adam Bellaire
23 октября 2008 в 12:55
4187

Вы также можете использовать ответ Маркуса (* символы подстановки) вне оператора case, если используете двойные скобки:

string='My long string'
if [[ $string == *"My long"* ]]; then
  echo "It's there!"
fi

Обратите внимание, что пробелы в строке стрелки необходимо заключать в двойные кавычки, а символы подстановки * должны находиться снаружи. Также обратите внимание, что используется простой оператор сравнения (т. Е. ==), а не оператор регулярного выражения =~.

Quinn Taylor
30 июля 2009 в 17:14
167

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

Jonik
16 ноября 2010 в 11:20
2

Хм, с этим точным кодом я получаю [[: not found. Есть идеи, что случилось? Я использую GNU bash версии 4.1.5 (1) в Ubuntu.

Dennis Williamson
17 декабря 2010 в 05:18
72

@Jonik: Возможно, вам не хватает шебанга или он указан как #!/bin/sh. Попробуйте вместо этого #!/bin/bash.

GuruM
7 сентября 2011 в 10:37
0

+1 за ваш ответ. Спасибо. Я смотрел код, в котором используется этот синтаксис. Хотя я догадался о намерении, теперь у меня есть подтверждение. Некоторое время пробовал использовать руководство по сценариям bash и Google, но не мог найти то, что хотел, пока не увидел ваш ответ. Вы можете дать ссылку на такое использование строк и подстановочных знаков? Спасибо!!

prolink007
19 октября 2012 в 16:32
0

@DennisWilliamson У меня та же проблема, что и у Джоника, но у меня правильный #!/bin/bash вверху. Что еще могло вызвать проблему?

prolink007
19 октября 2012 в 16:48
4

Я разобрался в проблеме. Если вы вызываете сценарий из другого сценария, убедитесь, что вы используете bash nameofscript.sh вместо sh nameofscript.sh.

Redsandro
5 декабря 2012 в 20:06
0

Безуспешно. Что не так в этом утверждении? if [["Oh My God" == *My*]]; then echo Yes! ; else echo no.. ; fi Возвращает нет. Это в bash / Ubuntu 12.10

Paul Price
22 января 2013 в 16:43
18

Оставьте пробел между скобками и содержимым.

Orwellophile
9 августа 2013 в 05:07
20

Вам не нужно заключать переменные в кавычки внутри [[]]. Это будет работать точно так же: [[$ string == $ Needle ]] && echo found

Reinstate Monica Please
9 января 2014 в 00:28
0

+1 к исходному ответу. Но редактирование в лучшем случае является субъективным, а в худшем - неточным (вам не нужно здесь цитировать $string, хотя это может быть хорошей практикой), и, очевидно, его следует откатить.

Dss
13 января 2014 в 16:57
1

Кажется, это не работает, когда у меня есть двоеточие «:» в строке if [[$ string == My: test ]]

user3153014
11 июня 2014 в 05:45
0

как проверить, содержит ли строка *?

nyuszika7h
11 июня 2014 в 17:53
19

@Orwellophile Осторожно! Вы можете опустить только двойные кавычки в первом аргументе [[. См. ideone.com/ZSy1gZ

Orwellophile
24 июня 2014 в 14:24
0

@ nyuszika7h - какой бардак :) Я бы использовал регулярное выражение, которое в bash4 все равно нельзя цитировать.

redolent
24 июля 2014 в 18:01
3

Кстати, убедитесь, что звездочки не в кавычках: if [[ " $args" == *" -l"* ]]

Shailen
3 августа 2014 в 14:56
2

Мне потребовалось много времени, чтобы понять, что с #!/bin/bash между каждым элементом оператора необходимы пробелы, например if [[ $input_var == "test" ]]

Tim S.
19 ноября 2014 в 16:16
0

@Dss упомянул, что это пространство, просто подумал, что добавлю, что вам нужно его избежать: if [[ $string == *My\ String* ]]

harish
18 февраля 2015 в 16:46
0

Я использовал выше, с той лишь разницей, что в сравнении менялись местами строка и подстрока, и это не сработало для меня, если бы я какое-то время был в тупике. Кто-нибудь знает почему?

F. Hauri
31 мая 2015 в 14:36
2

Предупреждение: это так называемый башизм ! Как отметил @DennisWilliamson, эта работа работает только под bash, но не с обычной оболочкой! (Я написал совместимую функцию, которая могла бы работать под плохой оболочкой, такой как busybox)

maxschlepzig
30 апреля 2017 в 15:11
1

@ Ф.Хаури, это не башизм. Он также работает с POSIX sh и ksh.

maxschlepzig
30 апреля 2017 в 15:21
0

@VasyaNovikov, 'Разделение слов и расширение имени пути не выполняются для слов между [[ и ]]' (bash (1))

VasiliNovikov
30 апреля 2017 в 20:08
0

@maxschlepzig верно. Я не знал этого, когда писал комментарий .. Удаляю старый комментарий и этот через пару часов ..

F. Hauri
1 мая 2017 в 05:33
2

@maxschlepzig Вы ошибаетесь: это башизм ! Позаботьтесь о том, чтобы ваш /bin/sh не был ссылкой на bash! Для себя я просто попробовал dash сейчас: dash: 2: [[: not found

maxschlepzig
1 мая 2017 в 09:58
1

@ F.Hauri, POSIX 2008 перечисляет [[ как неуказанное зарезервированное слово. Но все же: KSH 88 и /usr/xpg4/bin/sh под Solaris 10 («оболочка, соответствующая стандартам») оба понимают [[. Таким образом, это НЕ башизм.

sdaau
26 октября 2017 в 19:18
0

Я заметил, что если вы запустите эту команду if [[ $string == *"linux"* ]]; then в каталоге, содержащем файл README.linux, тогда *"linux"* расширится до README.linux, то есть * будет глобально - и поэтому сопоставление не удастся .

Fredrick Gauss
7 ноября 2017 в 06:51
3

Внимание! if [[ *"My long"* == $string ]]; не работает, а if [[ $string == *"My long"* ]]; работает. Есть ли кто-нибудь, чтобы это объяснить?

Yongwei Wu
19 января 2018 в 07:46
1

@sdaau Не воспроизводится в моем тесте под Bash. Никаких глобусов не произошло. На информационной странице bash на самом деле четко сказано: «Разделение слов и расширение имени файла не выполняется для слов между '[[' и ']]'»

Yongwei Wu
19 января 2018 в 07:49
1

@FredrickGauss На информационной странице Bash говорится: «Когда используются операторы '==' и '! =', Строка справа от оператора считается шаблоном и сопоставляется в соответствии с правилами, описанными ниже в * примечании Сопоставление с шаблоном: :. Если опция оболочки 'nocasematch' (см. Описание 'shopt' в * примечании The Shopt Builtin: :) включена, сопоставление выполняется без учета регистра буквенных символов. Возвращаемое значение - 0, если строка совпадает ('==') или не совпадает ('! =') с шаблоном, иначе 1. Любая часть шаблона может быть заключена в кавычки для принудительного сопоставления его как строки ".

Alexander Mills
2 мая 2018 в 06:23
0

почему бы не использовать == вместо =?

user
4 ноября 2019 в 03:12
0

Если переменная $string пуста, будет выдана синтаксическая ошибка. Ты можешь починить это?

JPM
21 сентября 2020 в 22:54
0

ошибка для меня, поскольку у меня есть кавычки в моих строках, которые мне нужно проверить.

Orwellophile
4 ноября 2020 в 06:58
0

@ nyuszika7h (вернулся после поиска в Google, чтобы что-то вспомнить) - извините, я не думаю, что мне действительно понравился ваш комментарий о цитировании второго аргумента. я не совсем уверен, как я себя чувствую. с одной стороны, полезно разрешить пользователю вводить подстановочные знаки и использовать их (без кавычек $ b) или не использовать их (в кавычках $ b), и все это с безопасностью подстановки. но я не совсем уверен, что дополнительная мощность компенсирует неизбежные ошибки из-за неправильного использования.

Small Boy
20 мая 2021 в 21:08
0

@ nyuszika7h «Осторожно! Вы можете опустить только двойные кавычки в первом аргументе [[.» Нет, дорогая, это неправильно . Второй аргумент тоже можно не цитировать. Пример в вашей ссылке касается подстановки и говорит: 1. Это происходит только во втором аргументе. 2. И, конечно, только без кавычек.

Jackt
22 июня 2021 в 00:10
0

что быстрее? это или = ~?

avatar
franzisk
20 апреля 2022 в 09:35
0

Вы можете использовать логику &&, чтобы быть более компактным

#!/bin/bash

# NO MATCH EXAMPLE
string="test"
[[ "$string" == *"foo"* ]] && {
        echo "YES"
}

# MATCH EXAMPLE
string="tefoost"
[[ "$string" == *"foo"* ]] && {
        echo "YES"
}
avatar
Piotr Henryk Dabrowski
30 ноября 2021 в 20:12
2

Принятый ответ правильный, но его трудно прочитать и понять.
Для проблем, связанных с поиском, вы всегда должны использовать идиому $needle in a $haystack.
Поскольку его рекомендуемая очередь редактирования заполнена, я публикую это:

haystack='There are needles here.'
if [[ "$haystack" == *"needle"* ]]; then
    echo "It's there!"
fi
avatar
Koichi Nakashima
27 марта 2020 в 10:42
3
case $string in (*foo*)
  # Do stuff
esac

Это тот же ответ, что и https://coderhelper.com/a/229585/11267590. Но простой стиль и совместимость с POSIX.

avatar
Pipo
17 марта 2020 в 10:34
3

Стандартный стог сена для иголок следующий с переменными

#!/bin/bash

needle="a_needle"
haystack="a_needle another_needle a_third_needle"
if [[ $haystack == *"$needle"* ]]; then
    echo "needle found"
else
    echo "needle NOT found"
fi
avatar
BobMonk
13 февраля 2020 в 00:22
0
msg="message"

function check {
    echo $msg | egrep [abc] 1> /dev/null

    if [ $? -ne 1 ];
    then 
        echo "found" 
    else 
        echo "not found" 
    fi
}

check

Это обнаружит любое появление a, b или c

avatar
FifthAxiom
4 декабря 2019 в 15:14
5

Поскольку вопрос POSIX / BusyBox закрыт без предоставления правильного ответа (ИМХО), я отправлю ответ здесь.

Самый короткий ответ:

[ ${_string_##*$_substring_*} ] || echo Substring found!

или

[ "${_string_##*$_substring_*}" ] || echo 'Substring found!'

Обратите внимание, что двойной хеш является обязательным с некоторыми оболочками (ash). Выше будет оцениваться [ stringvalue ], если подстрока не найдена. Ошибка не возвращается. Когда подстрока найдена, результат пуст и равен [ ]. Это вызовет код ошибки 1, поскольку строка полностью заменена (из-за *).

Самый короткий и распространенный синтаксис:

[ -z "${_string_##*$_substring_*}" ] && echo 'Substring found!'

или

[ -n "${_string_##*$_substring_*}" ] || echo 'Substring found!'

Еще один:

[ "${_string_##$_substring_}" != "$_string_" ] && echo 'Substring found!'

или

[ "${_string_##$_substring_}" = "$_string_" ] || echo 'Substring found!'

Обратите внимание на одинарный знак равенства!

avatar
Alex Skrypnyk
2 февраля 2019 в 06:03
5

Расширение вопроса, на который дан ответ здесь Как узнать, содержит ли строка другую строку в POSIX sh? :

Это решение работает со специальными символами:

# contains(string, substring)
#
# Returns 0 if the specified string contains the specified substring,
# otherwise returns 1.
contains() {
    string="$1"
    substring="$2"

    if echo "$string" | $(type -p ggrep grep | head -1) -F -- "$substring" >/dev/null; then
        return 0    # $substring is in $string
    else
        return 1    # $substring is not in $string
    fi
}

contains "abcd" "e" || echo "abcd does not contain e"
contains "abcd" "ab" && echo "abcd contains ab"
contains "abcd" "bc" && echo "abcd contains bc"
contains "abcd" "cd" && echo "abcd contains cd"
contains "abcd" "abcd" && echo "abcd contains abcd"
contains "" "" && echo "empty string contains empty string"
contains "a" "" && echo "a contains empty string"
contains "" "a" || echo "empty string does not contain a"
contains "abcd efgh" "cd ef" && echo "abcd efgh contains cd ef"
contains "abcd efgh" " " && echo "abcd efgh contains a space"

contains "abcd [efg] hij" "[efg]" && echo "abcd [efg] hij contains [efg]"
contains "abcd [efg] hij" "[effg]" || echo "abcd [efg] hij does not contain [effg]"

contains "abcd *efg* hij" "*efg*" && echo "abcd *efg* hij contains *efg*"
contains "abcd *efg* hij" "d *efg* h" && echo "abcd *efg* hij contains d *efg* h"
contains "abcd *efg* hij" "*effg*" || echo "abcd *efg* hij does not contain *effg*"
joeytwiddle
12 декабря 2019 в 10:34
2

Тест contains "-n" "n" здесь не работает, потому что echo -n проглотит -n как вариант! Популярным решением этой проблемы является использование вместо этого printf "%s\n" "$string".

avatar
Mike Q
5 октября 2018 в 18:54
26

Примеры для Bash 4+. Примечание: отказ от кавычек вызовет проблемы, если слова содержат пробелы и т. Д. Всегда заключайте кавычки в Bash, IMO.

Вот несколько примеров Bash 4+:

Пример 1, проверьте "да" в строке (без учета регистра):

    if [[ "${str, }" == *"yes"* ]] ;then

Пример 2, проверьте "да" в строке (без учета регистра):

    if [[ "$(echo "$str" | tr '[:upper:]' '[:lower:]')" == *"yes"* ]] ;then

Пример 3, проверьте "да" в строке (с учетом регистра):

     if [[ "${str}" == *"yes"* ]] ;then

Пример 4, проверьте "да" в строке (с учетом регистра):

     if [[ "${str}" =~ "yes" ]] ;then

Пример 5, точное соответствие (с учетом регистра):

     if [[ "${str}" == "yes" ]] ;then

Пример 6, точное соответствие (без учета регистра):

     if [[ "${str, }" == "yes" ]] ;then

Пример 7, точное соответствие:

     if [ "$a" = "$b" ] ;then

Пример 8, совпадение с подстановочными знаками .ext (без учета регистра):

     if echo "$a" | egrep -iq "\.(mp[3-4]|txt|css|jpg|png)" ; then

Наслаждайтесь.

hey
17 января 2021 в 22:08
1

Аааа - я понял это только после того, как узнал, что две запятые в ${str, } преобразуют $str в нижний регистр. Отличные решения / отличный список!

avatar
Ethan Post
11 апреля 2018 в 02:09
2

Я использую эту функцию (одна зависимость не включена, но очевидна). Он проходит тесты, указанные ниже. Если функция возвращает значение> 0, значит, строка найдена. Вместо этого вы можете так же легко вернуть 1 или 0.

function str_instr {
   # Return position of ```str``` within ```string```.
   # >>> str_instr "str" "string"
   # str: String to search for.
   # string: String to search.
   typeset str string x
   # Behavior here is not the same in bash vs ksh unless we escape special characters.
   str="$(str_escape_special_characters "${1}")"
   string="${2}"
   x="${string%%$str*}"
   if [[ "${x}" != "${string}" ]]; then
      echo "${#x} + 1" | bc -l
   else
      echo 0
   fi
}

function test_str_instr {
   str_instr "(" "'foo@host (dev,web)'" | assert_eq 11
   str_instr ")" "'foo@host (dev,web)'" | assert_eq 19
   str_instr "[" "'foo@host [dev,web]'" | assert_eq 11
   str_instr "]" "'foo@host [dev,web]'" | assert_eq 19
   str_instr "a" "abc" | assert_eq 1
   str_instr "z" "abc" | assert_eq 0
   str_instr "Eggs" "Green Eggs And Ham" | assert_eq 7
   str_instr "a" "" | assert_eq 0
   str_instr "" "" | assert_eq 0
   str_instr " " "Green Eggs" | assert_eq 6
   str_instr " " " Green "  | assert_eq 1
}
Peter Mortensen
1 января 2020 в 14:22
0

Ожидание! Что такое зависимость?

Ethan Post
2 января 2020 в 05:47
0

Функция "str_escape_special_characters". Он находится в файле arcshell_str.sh на GitHub. arcshell.io доставит вас туда.

pkfm
3 октября 2020 в 17:47
0

str_escape_special_characters, похоже, превратился в str_escape. см. arcshell_str.sh @ arclogicsoftware / arcshell

avatar
Leslie Satenstein
14 января 2017 в 05:36
6

Мой файл .bash_profile и как я использовал grep:

Если переменная среды PATH включает два моих каталога bin, не добавляйте их,

# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi

U=~/.local.bin:~/bin

if ! echo "$PATH" | grep -q "home"; then
    export PATH=$PATH:${U}
fi
codeforester
14 января 2017 в 06:01
1

Это ответ?

Mohamed Bana
7 февраля 2017 в 13:37
0

проголосовать. Зачем беспокоиться о том, чтобы узнать, как это делает Bash, когда более мощная команда grep, скорее всего, будет доступна. также расширите его немного дальше, сопоставив его со списком шаблонов: grep -q -E 'pattern1|...|patternN'.

avatar
Eduardo Cuomo
10 ноября 2016 в 14:56
3

Точное совпадение слова:

string='My long string'
exactSearch='long'

if grep -E -q "\b${exactSearch}\b" <<<${string} >/dev/null 2>&1
  then
    echo "It's there"
  fi
avatar
ride
3 марта 2016 в 19:12
5

Мне нравится sed.

substr="foo"
nonsub="$(echo "$string" | sed "s/$substr//")"
hassub=0 ; [ "$string" != "$nonsub" ] && hassub=1

Редактировать, логика:

  • Используйте sed, чтобы удалить экземпляр подстроки из строки

  • Если новая строка отличается от старой, подстрока существует

Zulan
5 марта 2016 в 14:04
3

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

avatar
Jahid
28 апреля 2015 в 19:55
11
[[ $string == *foo* ]] && echo "It's there" || echo "Couldn't find"
nicodjimenez
16 октября 2017 в 21:11
0

Я добавлю, что оператор echo "Couldn't find в конце - это хороший трюк для возврата 0 статусов выхода для этих совпадающих команд.

Jahid
17 октября 2017 в 05:56
0

@nicodjimenez, вы больше не можете настроить таргетинг на статус выхода с помощью этого решения. Статус выхода поглощен статусными сообщениями ...

nicodjimenez
17 октября 2017 в 10:02
1

Это именно то, что я имел в виду ... Если у вас нет || echo "Couldn't find", вы вернете статус выхода с ошибкой, если совпадения нет, чего вы, возможно, не захотите, если вы используете конвейер CI, например, где вы хотите все команды для возврата статусов выхода без ошибок

avatar
Samuel
31 декабря 2014 в 22:32
21

Как Пол упомянул в своем сравнении производительности:

if echo "abcdefg" | grep -q "bcdef"; then
    echo "String contains is true."
else
    echo "String contains is not true."
fi

Это совместимо с POSIX, как 'case "$ string" в' ответе, предоставленном Маркусом, но его немного легче читать, чем ответ оператора case. Также обратите внимание, что это будет намного медленнее, чем использование оператора case. Как указал Пол, не используйте его в цикле.

avatar
Paul Hedderly
27 августа 2014 в 19:42
69

Итак, на этот вопрос есть много полезных решений, но какое из них самое быстрое / использует меньше всего ресурсов?

Повторные тесты с использованием этого кадра:

/usr/bin/time bash -c 'a=two;b=onetwothree; x=100000; while [ $x -gt 0 ]; do TEST ; x=$(($x-1)); done'

Замена TEST каждый раз:

[[ $b =~ $a ]]           2.92 user 0.06 system 0:02.99 elapsed 99% CPU

[ "${b/$a//}" = "$b" ]   3.16 user 0.07 system 0:03.25 elapsed 99% CPU

[[ $b == *$a* ]]         1.85 user 0.04 system 0:01.90 elapsed 99% CPU

case $b in *$a):;;esac   1.80 user 0.02 system 0:01.83 elapsed 99% CPU

doContain $a $b          4.27 user 0.11 system 0:04.41 elapsed 99%CPU

(doContain был в ответе Ф. Хури)

И для хихиканья:

echo $b|grep -q $a       12.68 user 30.86 system 3:42.40 elapsed 19% CPU !ouch!

Таким образом, вариант простой замены предсказуемо выигрывает как в расширенном тесте, так и в случае. Кейс переносной.

Переход к 100000 greps предсказуемо болезненен! Верно старое правило об использовании внешних утилит без надобности.

Mad Physicist
13 июля 2016 в 16:28
7

Отличный тест. Убедил меня использовать [[ $b == *$a* ]].

tripleee
12 апреля 2018 в 06:59
2

Если я правильно это понимаю, case выигрывает с наименьшими общими затратами времени. Однако после $b in *$a звездочка отсутствует. Я получаю немного более быстрые результаты для [[ $b == *$a* ]], чем для case с исправленной ошибкой, но, конечно, это может зависеть и от других факторов.

tripleee
12 апреля 2018 в 08:41
1

ideone.com/5roEVt мой эксперимент с исправлением некоторых дополнительных ошибок и тестами для другого сценария (где строка фактически отсутствует в более длинной строке). Результаты во многом схожи; [[ $b == *$a* ]] работает быстро, а case почти так же быстро (и приятно POSIX-совместимым).

r a
19 февраля 2021 в 13:49
0

Условное выражение [[ $b == *$a* ]] и оператор case case $b in *$a):;;esac не эквивалентны в условии отсутствия совпадений. Обмен местами $a и $b приводит к получению кода выхода 1 для условного выражения [[ и кода выхода 0 для оператора case. Согласно help case: Статус выхода: Возвращает статус последней выполненной команды. Статус возврата равен нулю, если не сопоставлен шаблон , что, вероятно, не является ожидаемым поведением. Чтобы вернуть 1 в условии отсутствия совпадения, это должно быть: case $b in *$a*):;; *) false ;; esac

avatar
F. Hauri
8 декабря 2013 в 23:06
289

stringContain варианты (совместимые или независимые от регистра)

Поскольку эти ответы о переполнении стека говорят в основном о Bash, я опубликовал независимую от регистра функцию Bash в самом низу этого поста ...

Так или иначе, вот мой

Совместимый ответ

Поскольку уже есть много ответов с использованием специфичных для Bash функций, есть способ работать в оболочках с меньшими возможностями, например BusyBox:

[ -z "${string##*$reqsubstr*}" ]

На практике это может дать:

string='echo "My string"'
for reqsubstr in 'o "M' 'alt' 'str';do
  if [ -z "${string##*$reqsubstr*}" ] ;then
      echo "String '$string' contain substring: '$reqsubstr'."
    else
      echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
  done

Это было протестировано с использованием Bash, Dash, KornShell (ksh) и ash, ash, (всегда)

String 'echo "My string"' contain substring: 'o "M'.
String 'echo "My string"' don't contain substring: 'alt'.
String 'echo "My string"' contain substring: 'str'.

В одну функцию

По просьбе @EeroAaltonen, вот версия той же демонстрации, протестированная в тех же оболочках:

myfunc() {
    reqsubstr="$1"
    shift
    string="$@"
    if [ -z "${string##*$reqsubstr*}" ] ;then
        echo "String '$string' contain substring: '$reqsubstr'.";
      else
        echo "String '$string' don't contain substring: '$reqsubstr'."
    fi
}

Затем:

$ myfunc 'o "M' 'echo "My String"'
String 'echo "My String"' contain substring 'o "M'.

$ myfunc 'alt' 'echo "My String"'
String 'echo "My String"' don't contain substring 'alt'.

Примечание: вы должны экранировать или заключать двойные кавычки и / или двойные кавычки:

$ myfunc 'o "M' echo "My String"
String 'echo My String' don't contain substring: 'o "M'.

$ myfunc 'o "M' echo \"My String\"
String 'echo "My String"' contain substring: 'o "M'.

Простая функция

Это было протестировано в BusyBox, Dash и, конечно же, в Bash:

stringContain() { [ -z "${2##*$1*}" ]; }

Тогда сейчас:

$ if stringContain 'o "M3' 'echo "My String"';then echo yes;else echo no;fi
no
$ if stringContain 'o "M' 'echo "My String"';then echo yes;else echo no;fi
yes

... Или, если представленная строка может быть пустой, как указано @Sjlver, функция будет выглядеть так:

stringContain() { [ -z "${2##*$1*}" ] && [ -z "$1" -o -n "$2" ]; }

или, как было предложено в комментарии Адриана Гюнтера, избегая переключателей -o:

stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ];};}

Конечная (простая) функция:

И инвертирование тестов, чтобы сделать их потенциально более быстрыми:

stringContain() { [ -z "$1" ] || { [ -z "${2##*$1*}" ] && [ -n "$2" ];};}

С пустыми строками:

$ if stringContain '' ''; then echo yes; else echo no; fi
yes
$ if stringContain 'o "M' ''; then echo yes; else echo no; fi
no

Независимо от регистра (только Bash!)

Для проверки строк без учета регистра просто преобразуйте каждую строку в нижний регистр:

stringContain() {
    local _lc=${2, }
    [ -z "$1" ] || { [ -z "${_lc##*${1, }*}" ] && [ -n "$2" ] ;} ;}

Чек:

stringContain 'o "M3' 'echo "my string"' && echo yes || echo no
no
stringContain 'o "My' 'echo "my string"' && echo yes || echo no
yes
if stringContain '' ''; then echo yes; else echo no; fi
yes
if stringContain 'o "M' ''; then echo yes; else echo no; fi
no

Eero Aaltonen
10 декабря 2013 в 08:35
1

Было бы даже лучше, если бы вы могли придумать способ передать это функции.

F. Hauri
6 мая 2014 в 18:23
2

@EeroAaltonen Как вам моя (новая добавленная) функция?

eggmatters
15 июля 2014 в 20:20
2

Я знаю! найти . -имя "*" | xargs grep "myfunc" 2> / dev / null

F. Hauri
15 июля 2014 в 22:14
0

@eggmatters Вопрос означает строку , которая содержит строку (не файл, содержащий строку).

eggmatters
16 июля 2014 в 23:15
1

@ F.Hauri Извините, это была шутка по поводу вашего комментария к EuroAaltonen. Команда find не имеет абсолютно никакого отношения к вопросу, размещенному в этой ветке.

Eero Aaltonen
25 сентября 2014 в 11:15
0

$ F.Hauri Это то, о чем я думал и на что надеялся. Единственное, что я хотел бы изменить, - это название. Я предлагаю "stringContain", поскольку поддерживаются как минимум целые числа.

Sjlver
24 октября 2014 в 12:14
7

Это замечательно, потому что так совместимо. Однако есть одна ошибка: он не работает, если строка стога сена пуста. Правильная версия: string_contains() { [ -z "${2##*$1*}" ] && [ -n "$2" -o -z "$1" ]; } Последняя мысль: содержит ли пустая строка пустую строку? Версия выше - да (из-за части -o -z "$1").

user3439968
14 ноября 2014 в 19:11
3

+1. Очень хороший! Для меня я изменил заказ stringContain () {[-z "$ {1 ## * $ 2 *}"] && [-z "$ 2" -o -n "$ 1"]; }; «Искать где» «Что найти». Работа в busybox. Принятый ответ выше не работает в busybox.

AKS
21 октября 2016 в 22:13
0

Аналогично, если [-z $ {строка %% * $ subreqstr *}]; затем эхо там; иначе эхо нет; fi # тоже будет работать.

F. Hauri
25 августа 2017 в 20:53
0

@ArunSangal Да, технически это тот же способ мышления, но на практике может быть какая-то разница ... Я бы позволил вам попробовать это на нескольких тысячах тестов, чтобы увидеть, может ли bash быть худшим в в одну сторону, чем в другую ... ;-)

F. Hauri
12 февраля 2018 в 15:30
0

Особый случай: Строка для поиска - это первое слово в каждой строке ( processor в <500384710845> см. <5003847847838> ответ на вопрос Как получить количество процессоров / ядер в Linux из командной строки ?!

Adrian Günter
10 апреля 2018 в 16:39
1

Расширения -a и -o для [ не совсем переносимы, поскольку POSIX определяет поведение только для четырех операторов. [ -n "$2" ] && [ -z "${2##*$1*}" ] || [ -z "$1" ] является переносимым и следует поведению реализаций из других языков, хотя я думаю, что переключение аргументов было бы еще более ясным (стог сена перед иглой).

F. Hauri
11 апреля 2018 в 14:50
0

@ AdrianGünter Поскольку [ - это команда, и && разделение между двумя командами, [ -z "$1" -o -n "$2" ] нужно учитывать только, не более четырех операторов (фактически два оператора, как -n и -z используют неявные операторы).

Adrian Günter
12 апреля 2018 в 00:55
1

@ F.Hauri Я лениво называл оба оператора (-a, -o, -n, -z, ...) и основные параметры / операнды ($1, $2, ...) как операторы (или еще лучше, аргументы ) до [ (AKA test). Дело в том, что [ -z "$1" -o -n "$2" ] передает пять аргументов в [, которые не указаны и, следовательно, ненадежны и непереносимы. См .: unix.stackexchange.com/a/57843/83127 и pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html <2781799

F. Hauri
12 апреля 2018 в 06:20
0

@ AdrianGünter. Гм .. осторожность при переводе логического значения: a & ( b | c ) не то же самое, что и c & b | a!

tripleee
12 апреля 2018 в 06:49
0

Думаю, даже в Busybox есть case.

Adrian Günter
12 апреля 2018 в 17:48
1

@ F.Hauri Я изменил порядок здесь для дальнейшей оптимизации, но [ -z "$1" ] || [ -n "$2" ] && [ -z "${2##*$1*}" ] и [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ] } функционально эквивалентны, за исключением того, что ваша версия менее эффективна. Учтите: если $1, подстрока иглы / поиска пуста (""), то вам вообще не нужно проверять [ -z "${2##*$1*}" ], так как каждую строку (включая пустую!) содержит "". Если $1 - пустая строка, strContain всегда должен возвращать успех (0). Если вы протестируете наши версии бок о бок, вы обнаружите, что они функционально эквивалентны.

Pryftan
21 декабря 2018 в 14:29
0

Неужели это более бедная оболочка? Возможно, он более ограничен, но он статически связан, не так ли? Это отлично подходит для восстановления системы (некоторых ошибок или ошибок) и других подобных вещей. Может быть, в таких ситуациях и не обязательно иметь эту функцию, но мало ли. Это действительно дополняет другие ответы!

Sandburg
11 января 2019 в 08:33
1

Приятно сказать, если что-то bash, ksh или ванильное shell совместимо, спасибо

S.S. Anne
23 мая 2020 в 23:38
0

Это легко изменить, чтобы проверить, не содержит ли строка подстроку: все, что вам нужно сделать, это использовать -n вместо -z или полностью опустить любые параметры.

F. Hauri
25 мая 2020 в 06:19
0

@ С.С. Энн if ! stringContain "$1" "$string";then ...

S.S. Anne
25 мая 2020 в 16:27
0

Нет, я говорю, что это легко изменить, чтобы проверить, не содержит ли строка другой (и я уже знаю, как это сделать). Двойное отрицание неплохо и не сбивает с толку.

avatar
Yordan Georgiev
26 августа 2013 в 10:13
12

Этот ответ переполнения стека был единственным, улавливающим символы пробела и тире:

# For null cmd arguments checking   
to_check=' -t'
space_n_dash_chars=' -'
[[ $to_check == *"$space_n_dash_chars"* ]] && echo found
Peter Mortensen
1 января 2020 в 13:43
0

Это ответ на тот же вопрос.

avatar
kevinarpe
1 декабря 2012 в 15:41
30

Это также работает:

if printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
  printf "Found needle in haystack"
fi

И отрицательный результат:

if ! printf -- '%s' "$haystack" | egrep -q -- "$needle"
then
  echo "Did not find needle in haystack"
fi

Я полагаю, этот стиль немного более классический - меньше зависит от функций оболочки Bash.

Аргумент -- - это чистая паранойя POSIX, используемая для защиты от входных строк, подобных параметрам, таким как --abc или -a.

Примечание: в тесном цикле этот код будет намного медленнее, чем использование внутренних функций оболочки Bash, так как один (или два) отдельных процесса будут созданы и соединены через каналы.

michael
10 августа 2013 в 05:43
5

... но OP не говорит, какая версия bash; например, более старые bash (такие как Solaris часто имеют) могут не включать эти новые функции bash. (Я столкнулся с этой точной проблемой (сопоставление шаблонов bash не реализовано) на solaris w / bash 2.0)

nyuszika7h
11 июня 2014 в 18:03
2

echo не переносится, вместо него следует использовать printf '%s' "$haystack.

kevinarpe
16 августа 2014 в 11:15
0

@ nyuszika7h: меня не было дома echo непереносимо. Будет ли /bin/echo работать?

nyuszika7h
16 августа 2014 в 11:18
2

Нет, просто избегайте echo для чего угодно, кроме буквального текста без экранирования, который не начинается с -. Он может работать для вас, но его нельзя переносить. Даже echo в bash будет вести себя по-разному в зависимости от того, установлен ли параметр xpg_echo. P.S .: Я забыл закрыть двойные кавычки в моем предыдущем комментарии.

kevinarpe
17 марта 2015 в 04:52
0

@ nyuszika7h: Знаете ли вы, переносной ли printf -- <anything> или только printf <anything>? По привычке на всякий случай использовал printf -- <anything>.

nyuszika7h
17 марта 2015 в 13:45
1

@kevinarpe Я не уверен, -- не указан в спецификации POSIX для printf, но вы все равно должны использовать printf '%s' "$anything", чтобы избежать проблем, если $anything содержит % персонаж.

kevinarpe
17 июня 2016 в 07:14
0

@ nyuszika7h: Что касается поддержки --, я нашел эту спецификацию POSIX для getopt(): pubs.opengroup.org/onlinepubs/9699919799/functions/getopt.html. Как вы думаете, можно ли предположить, что если printf определен / совместим с POSIX, то -- также будет поддерживаться?

nyuszika7h
17 июня 2016 в 10:49
1

@kevinarpe Исходя из этого, вероятно, так и есть.

avatar
Kurt Pfeifle
1 июля 2012 в 11:31
5

Я обнаружил, что эта функция нужна довольно часто, поэтому я использую самодельную функцию оболочки в моем .bashrc, подобную этой, которая позволяет мне повторно использовать ее так часто, как мне нужно, с легко запоминающимся именем:

function stringinstring()
{
    case "$2" in
       *"$1"*)
          return 0
       ;;
    esac
    return 1
}

Чтобы проверить, содержится ли $string1 (скажем, abc ) в $string2 (скажем, 123abcABC ), мне просто нужно выполнить проверку для возврата 8473206 и запустить значение, например

stringinstring "$str1" "$str2"  &&  echo YES  ||  echo NO
elyase
11 декабря 2012 в 21:34
0

[["$ str" == $ substr ]] && echo ДА || эхо НЕТ

nyuszika7h
11 июня 2014 в 18:08
0

Я почти уверен, что хак x требуется только для очень старых оболочек.

Mikhail T.
24 февраля 2021 в 15:46
0

Правильное - и сразу узнаваемое - имя для вашей функции будет strstr() :-)

Kurt Pfeifle
25 февраля 2021 в 09:32
0

@MikhailT .: не стесняйтесь обращаться с этим как хотите ... :-)

avatar
chemila
11 ноября 2011 в 05:51
11

Один:

[ $(expr $mystring : ".*${search}.*") -ne 0 ] && echo 'yes' ||  echo 'no'
michael
10 августа 2013 в 05:50
2

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

michael
4 марта 2014 в 19:13
0

@AloisMahdal Я никогда не голосовал против, я просто постулирую, почему были даны отрицательные голоса. Предупреждающий комментарий. Я использую expr в редких случаях, когда переносимость не позволяет использовать bash (например, несогласованное поведение в старых версиях), tr (непоследовательно везде) или sed (иногда слишком медленно). Но исходя из личного опыта, всякий раз, когда я перечитываю эти expr -измы, мне приходится возвращаться на страницу руководства. Итак, я бы просто прокомментировал, что каждое использование expr должно быть прокомментировано ...

tripleee
10 февраля 2016 в 18:12
1

Было время, когда у вас была только оригинальная оболочка Bourne. В нем отсутствовали некоторые обычно необходимые функции, поэтому для их выполнения были реализованы такие инструменты, как expr и test. В наши дни обычно есть инструменты получше, многие из них встроены в любую современную оболочку. Думаю, test все еще висит там, но, похоже, никто не пропал без вести expr.

Svet
3 мая 2021 в 23:11
0

Голосование за поддержку, поскольку мне нужно было что-то, что работало бы в оболочке Bourne, а все остальное, похоже, специфично для bash.

avatar
andreas
27 августа 2010 в 19:19
3

Попробуйте oobash.

Это строковая библиотека в стиле объектно-ориентированного программирования для Bash 4. Она поддерживает немецкие умляуты. Написано на Bash.

Доступно множество функций: -base64Decode, -base64Encode, -capitalize, -center, -charAt, -concat, -contains, <-count6024>, <-count60226 >, -reverse, -hashCode, -indexOf, -isAlnum, -isAlpha, -isAscii, -isDigit, -isEmpty, <-isHexDigit60>24, <67402248> -isUpperCase, -isVisible, -lastIndexOf, -length, -matches, -replaceAll, -replaceFirst, -startsWith, -substring, -startsWith, -substring, <672560258760> >, -trim и -zfill.

Посмотрите на , содержащий пример:

[Desktop]$ String a testXccc
[Desktop]$ a.contains tX
true
[Desktop]$ a.contains XtX
false

oobash доступен на Sourceforge.net.

avatar
Stefan
9 февраля 2009 в 06:15
20

Как насчет этого:

text="   <tag>bmnmn</tag>  "
if [[ "$text" =~ "<tag>" ]]; then
   echo "matched"
else
   echo "not matched"
fi
user49586
9 февраля 2009 в 06:37
2

= ~ предназначен для сопоставления регулярных выражений, поэтому слишком мощный для цели OP.

avatar
Jadu Saikia
21 декабря 2008 в 14:27
5

grep -q полезен для этой цели.

То же, используя awk:

string="unix-bash 2389"
character="@"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

Вывод:

Не найдено

string="unix-bash 2389"
character="-"
printf '%s' "$string" | awk -vc="$character" '{ if (gsub(c, "")) { print "Found" } else { print "Not Found" } }'

Вывод:

Найдено

Первоисточник: http://unstableme.blogspot.com/2008/06/bash-search-letter-in-string-awk.html

nyuszika7h
11 июня 2014 в 18:14
3

echo не переносится, вместо него следует использовать printf '%s' "$string". Я редактирую ответ, потому что пользователя больше не существует.

starbeamrainbowlabs
1 мая 2020 в 00:36
0

Каким образом echo не переносится, @ nyuszika7h?

avatar
Mark Baker
27 октября 2008 в 14:57
171

Вы должны помнить, что сценарии оболочки - это не столько язык, сколько набор команд. Инстинктивно вы думаете, что этот «язык» требует от вас следовать if с [ или [[. Обе это просто команды, которые возвращают статус выхода, указывающий на успех или неудачу (как и любая другая команда). По этой причине я бы использовал grep, а не команду [.

Просто сделайте:

if grep -q foo <<<"$string"; then
    echo "It's there"
fi

Теперь, когда вы думаете о if как о тестировании статуса выхода следующей за ним команды (с точкой с запятой), почему бы не пересмотреть источник тестируемой строки?

## Instead of this
filetype="$(file -b "$1")"
if grep -q "tar archive" <<<"$filetype"; then
#...

## Simply do this
if file -b "$1" | grep -q "tar archive"; then
#...

Параметр -q заставляет grep ничего не выводить, поскольку нам нужен только код возврата. <<< заставляет оболочку расширять следующее слово и использовать его в качестве входных данных для команды, однострочной версии << здесь документа (я не уверен, является ли это стандартным или Bashism).

alex.pilon
20 октября 2011 в 17:03
7

они называются здесь строки (3.6.7) Я считаю, что это башизм

larsr
19 декабря 2011 в 12:45
13

можно также использовать Замена процесса if grep -q foo <(echo somefoothing); then

nyuszika7h
11 июня 2014 в 18:05
0

Обратите внимание, что echo нельзя переносить, если вы передаете переменную, используйте вместо него printf '%s' "$string.

Bruno Bronosky
28 марта 2015 в 07:10
0

@ nyuszika7h echo сам по себе довольно портативен. Флаги нет. Если вы думаете о -e или -n, используйте printf

F. Hauri
20 апреля 2015 в 08:40
6

Стоимость этого очень высока: выполнение grep -q foo <<<"$mystring" подразумевает 1 вилку и составляет bashism , а echo $mystring | grep -q foo подразумевает 2 вилки (одна для трубы, а вторая для работы /path/to/grep).

tripleee
12 апреля 2018 в 06:45
1

@BrunoBronosky echo без флагов может по-прежнему иметь неожиданные проблемы с переносимостью, если строка аргумента содержит последовательности обратной косой черты. Ожидается, что echo "nope\c" на некоторых платформах будет работать как echo -e "nope" на некоторых других. printf '%s' "nope" против printf '%s\n' 'nope\c'

ahoffer
6 июня 2018 в 05:07
0

@TechZilla Помните, мы говорим о сценарии Bash. Никто не станет писать сценарий Bash для кода, критичного к производительности.

Wang Shaowei
14 апреля 2020 в 01:41
0

Я проверяю это

avatar
Matt Tardiff
23 октября 2008 в 20:10
757

Если вы предпочитаете подход регулярного выражения:

string='My string';

if [[ $string =~ "My" ]]; then
   echo "It's there!"
fi
blast_hardcheese
14 февраля 2012 в 05:10
2

Пришлось заменить регулярное выражение egrep в сценарии bash, это сработало отлично!

bukzor
5 июня 2013 в 18:15
117

Оператор =~ уже ищет совпадение по всей строке; .* здесь посторонние. Кроме того, кавычки обычно предпочтительнее обратной косой черты: [[ $string =~ "My s" ]]

seanf
12 мая 2015 в 00:55
18

Котировки @bukzor перестали работать с Bash 3.2+: tiswww.case.edu/php/chet/bash/FAQ E14). Вероятно, лучше всего присвоить переменной (используя кавычки), а затем сравнить. Как это: re="My s"; if [[ $string =~ $re ]]

KrisWebDev
24 января 2016 в 14:57
45

Проверьте, действительно ли НЕ содержит строку: if [[ ! "abc" =~ "d" ]] верно.

Douwe van der Leest
1 августа 2018 в 11:40
1

Обратите внимание, что порядок, в котором выполняется проверка, имеет значение. Вывод следующей строки кода будет направлен вперед 2. number=2; if [[ "1, 2, 4, 5" = *${number}* ]]; then echo forward $number; fi; if [[ *${number}* = "1, 2, 4, 5" ]]; then echo backwards $number; fi;

Wolfson
27 апреля 2020 в 08:49
0

@bukzor благодарит за четкое указание значения оператора =~, который проверяет совпадение. Исходя из Matlab, где ~= - это оператор not equal, это меня очень смутило в начале.

hychou
7 мая 2020 в 08:20
0

Сроки time for i in {1..100000}; do [[ "abcfewgwbzsgreagreagrw" == *"bzsgre"* ]]; done и time for i in {1..100000}; do [[ "abcfewgwbzsgreagreagrw" =~ "bzsgre" ]]; done. Мой компьютер показал, что =~ занимает примерно в два раза больше времени, чем ==.

Hugo Licon
20 июля 2020 в 23:33
0

что, если мне нужно, чтобы он был нечувствительным к регистру?

Orwellophile
4 ноября 2020 в 06:51
1

@hychou Любой, кто использует регулярные выражения для развлечения и получения прибыли, скажет, что только занимает вдвое больше времени, чем при использовании без регулярных выражений = полная сделка!

hychou
4 ноября 2020 в 07:07
0

Регулярное выражение @Orwellophile может делать гораздо более мощные вещи. Но в этом конкретном вопросе (содержит ли str1 str2) регулярное выражение является излишним и требует больше времени. Поэтому ИМО, это дело не торг.

avatar
ephemient
23 октября 2008 в 14:35
98

Принятый ответ - лучший, но, поскольку есть несколько способов сделать это, вот другое решение:

if [ "$string" != "${string/foo/}" ]; then
    echo "It's there!"
fi

${var/search/replace} - это $var с заменой первого экземпляра search на replace, если он найден (не меняется $var). Если вы попытаетесь заменить foo ничем, а строка изменилась, то очевидно, что foo был найден.

TPoschel
8 октября 2010 в 12:41
5

вышеприведенное решение ephemient:> `if [" $ string "! =" $ {string / foo /} "]; затем эхо "Это там!" fi` полезен при использовании оболочки BusyBox ash . Принятое решение не работает с BusyBox, потому что некоторые регулярные выражения bash не реализованы.

nitinr708
1 августа 2017 в 08:58
2

неравенство различия. Довольно странная мысль! я люблю это

venimus
12 июля 2019 в 17:31
1

если ваша строка не 'foo', хотя

BuvinJ
15 октября 2019 в 20:25
0

Я сам написал это же решение (потому что мой интерпретатор не принимал самые популярные ответы), затем пошел искать лучшее, но нашел это!

hanshenrik
1 сентября 2020 в 19:30
0

похоже, у меня не работает: запущенный Ubuntu Mate 20.04, $XDG_CURRENT_DESKTOP содержит MATE, и запущенный: if [ "$XDG_CURRENT_DESKTOP" != "${string/GNOME/}" ]; then echo MATCHES GNOME fi печатает СООТВЕТСТВИЯ GNOME ... он думает, что "MATE" соответствует "GNOME" ... dafuq?

avatar
Marcus Griep
23 октября 2008 в 12:47
414

Я не уверен в использовании оператора if, но вы можете получить аналогичный эффект с помощью оператора case:

case "$string" in 
  *foo*)
    # Do stuff
    ;;
esac
technosaurus
4 января 2014 в 17:02
90

Это, вероятно, лучшее решение, поскольку оно переносимо в оболочки posix. (иначе говоря, никаких башизмов)

P.P
17 декабря 2015 в 23:27
34

@technosaurus Мне довольно странно критиковать "башизм" в вопросе, в котором есть только тег bash :)

Carl Smotricz
3 июня 2016 в 07:56
49

@ P.P. Это не столько критика, сколько предпочтение более универсального решения более ограниченному. Пожалуйста, примите во внимание, что годы спустя люди (вроде меня) будут останавливаться, чтобы найти этот ответ, и, возможно, будут рады найти тот, который будет полезен в более широком контексте, чем исходный вопрос. Как говорят в мире Open Source: «выбор - хорошо!»

maxschlepzig
1 мая 2017 в 10:00
2

@technosaurus, FWIW [[ $string == *foo* ]] также работает в некоторых POSIX-совместимых версиях sh (например, /usr/xpg4/bin/sh в Solaris 10) и ksh (> = 88)

technosaurus
1 мая 2017 в 22:28
0

@maxschlepzig ... нет, если в $ IFS есть символы, такие как пробел, новая строка, табуляция или определенный пользователем разделитель ... оператор case работает, хотя и без странных смешанных цитат или необходимости нажимать и выталкивать IFS

maxschlepzig
1 мая 2017 в 22:39
0

@technosaurus, ты имеешь в виду из-за разбиения слов? С [[ нет разделения слов (см., Например, ksh(1)). Этот пример string="hello foo world"; [[ $string == *foo* ]] && echo true работает у меня, как и ожидалось. Даже с ksh 88. Да, в новой оболочке со значением по умолчанию IFS (т.е. пробел + новая строка + табуляция).

tripleee
12 апреля 2018 в 06:40
0

@maxschlepzig Значит, они не совместимы с POSIX. Очевидно, что Ksh - это оболочка Korn, а не POSIX sh; а Solaris 10 XPG sh - это определенно не POSIX.

maxschlepzig
12 апреля 2018 в 18:58
0

@tripleee, никто не утверждал, что ksh - это POSIX sh. И вы ошибаетесь насчет XPG4: «расширенный набор POSIX.1-1990, POSIX.2-1992 и POSIX.2a-1992, содержащий расширения стандартов POSIX из XPG3» XPG4 (5). Вы также можете спросить себя, какую версию sh Sun использовала для получения сертификата соответствия POSIX.

tripleee
13 апреля 2018 в 03:57
0

Тогда по той же логике Bash - это POSIX. Утверждать, что это функция некоторых оболочек POSIX, просто вводит в заблуждение; это определенно функция, не относящаяся к POSIX, и поэтому независимо от того, являются ли эти оболочки POSIX или нет, не имеет значения. Как вы сказали, оболочка содержит расширения, выходящие за рамки POSIX.

Ray Foss
25 марта 2019 в 14:50
3

Busybox ash не обрабатывает звездочки в [[ ... переключатель корпуса работал!