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

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

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

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

41 голос | спросил Lucio 25 Mayam13 2013, 03:35:07

7 ответов


24

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

my_string=abc
substring=ab
if [ "${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 он не будет изменен.

ответил edwin 25 Mayam13 2013, 03:54:03
41

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

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

Итак, вы можете использовать эту форму как-то вроде

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

Изменить: исправлено "= ~", перевернулся.

ответил demure 25 Mayam13 2013, 03:56:28
12

Использование bash шаблонов имен файлов (так называемые шаблоны glob)

substr=ab
[[ abc == *"$substr"* ]] && echo yes || echo no    # yes
[[ bcd == *"$substr"* ]] && echo yes || echo no    # no
ответил glenn jackman 25 Maypm13 2013, 22:12:02
10

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

 substr=ab
for 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}'"
    fi
done
 substr=ab
for 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}'"
    fi
done

Оба вывода выше:

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

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

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

ответил Richard Hansen 30 Mayam13 2013, 03:01:51
5

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

[[ $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 сказал, но помните, что если вы обернете весь второй член в двойных кавычках, он переключит тест на literal .

Источник: http://tldp.org/LDP/abs/html/Сравнение-ops.html

ответил Campa 29 Mayam13 2013, 10:36:13
5

утверждение case case

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

#!/bin/bash
case "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/sh

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

main(){
   if is_substring "ab" "abcdefg"
   then
       echo "ab is substring"
   fi
}

main [email protected]

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

$ 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
ответил Sergiy Kolodyazhnyy 25 SunEurope/Moscow2016-12-25T00:33:41+03:00Europe/Moscow12bEurope/MoscowSun, 25 Dec 2016 00:33:41 +0300 2016, 00:33:41
3

Как и ответ edwin, но с улучшенной переносимостью для posix & ksh, и прикосновение менее шумно, чем у Ричарда:

substring=ab

string=abc
if [ "$string" != "${string%$substring*}" ]; then
    echo "$substring IS in $string"
else
    echo "$substring is NOT in $string"
fi

string=bcd
if [ "$string" != "${string%$substring*}" ]; then
    echo "$string contains $substring"
else
    echo "$string does NOT contain $substring"
fi

Вывод:

abc contains ab
bcd does NOT contain ab
ответил laubster 7 Jpm1000000pmWed, 07 Jan 2015 20:42:25 +030015 2015, 20:42:25

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132