Как определить, является ли строка подстрокой другой в bash?

Я хочу посмотреть, находится ли строка внутри часть из другой строки.
напр.:

'ab' in 'abc' -> true'ab' in 'bcd' -> false

Как я могу сделать это в условном сценарии bash?

[[ "bcd" =~ "ab" ]]
[[ "abc" =~ "ab" ]]

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

Таким образом, вы могли бы использовать эту форму что-то вроде

var1="ab"var2="bcd"if [[ "$var2" =~ "$var1" ]]; then    echo "pass"else    echo "fail"fi

Редактировать: исправил "=~", перевернул.

Вы можете воспользоваться формой ${VAR/subs} где VAR содержит строку большего размера иsubs это подстрока, которую вы пытаетесь найти:

my_string=abcsubstring=abif [ "${my_string/$substring}" = "$my_string" ] ; then  echo "${substring} is not in ${my_string}"else  echo "${substring} was found in ${my_string}"fi

Это работает, потому что ${VAR/subs} равно $VAR но с первым вхождением строки subs удаляются, в частности, если $VAR не содержит слова subs он не будет изменен.

Использование bash шаблоны имен файлов (он же "глобусные" паттерны)

substr=ab[[ abc == *"$substr"* ]] && echo yes || echo no    # yes[[ bcd == *"$substr"* ]] && echo yes || echo no    # no

Следующие два подхода будут работать в любой POSIX-совместимой среде, а не только в bash:

substr=abfor s in abc bcd; do    if case ${s} in *"${substr}"*) true;; *) false;; esac; then        printf %s\\n "'${s}' contains '${substr}'"    else        printf %s\\n "'${s}' does not contain '${substr}'"    fidone
substr=abfor s in abc bcd; do    if printf %s\\n "${s}" | grep -qF "${substr}"; then        printf %s\\n "'${s}' contains '${substr}'"    else        printf %s\\n "'${s}' does not contain '${substr}'"    fidone

Оба вышеприведенных вывода:

'abc' contains 'ab''bcd' does not contain 'ab'

Первое имеет то преимущество, что не порождает отдельного grep процесс.

Обратите внимание, что я использую printf %s\\n "${foo}" вместо echo "${foo}" потому что echo может искалечить ${foo} если он содержит обратную косую черту.

заявление о подставном случае

Это самое портативное решение, будет работать даже на старых оболочках Bourne и Korn shell

#!/bin/bashcase "abcd" in    *$1*) echo "It's a substring" ;;    *) echo "Not a substring" ;;esac

Пробный запуск:

$ ./case_substr.sh "ab"                                                                                           It's a substring$ ./case_substr.sh "whatever"                                                                                     Not a substring

Обратите внимание, что вам не нужно специально использовать echo Вы можете использовать exit 1 и exit 0 чтобы обозначить успех или неудачу.

Что мы также могли бы сделать, так это создать функцию (которую при необходимости можно использовать в больших скриптах) с определенными возвращаемыми значениями (0 при совпадении, 1 при отсутствии совпадения):

$ ./substring_function.sh                                  ab is substring$ cat substring_function.sh                                #!/bin/shis_substring(){    case "$2" in        *$1*) return 0;;        *) return 1;;    esac}main(){   if is_substring "ab" "abcdefg"   then       echo "ab is substring"   fi}main $@

grep

$ grep -q 'ab' <<< "abcd" && echo "it's a substring" || echo "not a substring"                                    it's a substring

Этот конкретный подход полезен с операторами if-else в bash. Также в основном портативные

awk

$ awk '$0~/ab/{print "it is a substring"}' <<< "abcd"                                                             it is a substring

Питон

$ python -c 'import sys;sys.stdout.write("it is a substring") if "ab" in sys.stdin.read() else exit(1)' <<< "abcd"it is a substring

Рубин

$ ruby -e ' puts "is substring" if  ARGV[1].include? ARGV[0]'  "ab" "abcdef"                                             is substring

Обращайте внимание на [[ и ":

[[ $a == z* ]]   # True if $a starts with an "z" (pattern matching).[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).[ $a == z* ]     # File globbing and word splitting take place.[ "$a" == "z*" ] # True if $a is equal to z* (literal matching).

Итак, как сказал @ glenn_jackman, но имейте в виду, что если вы заключите весь второй член в двойные кавычки, это переключит тест на буквальный соответствие.

Источник: http://tldp.org/LDP/abs/html/comparison-ops.html

Похоже на ответ Эдвина, но с улучшенной переносимостью для posix и ksh и немного менее шумным, чем у Ричарда:

substring=abstring=abcif [ "$string" != "${string%$substring*}" ]; then    echo "$substring IS in $string"else    echo "$substring is NOT in $string"fistring=bcdif [ "$string" != "${string%$substring*}" ]; then    echo "$string contains $substring"else    echo "$string does NOT contain $substring"fi

Выход:

abc contains abbcd does NOT contain ab