Як визначити, чи рядок є підрядком іншого в bash?


49

Я хочу дізнатися, чи є рядок всередині частини іншої рядки.
наприклад:

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

Як я можу це зробити в умовному режимі bash?

Відповіді:


27

Ви можете скористатися формою, ${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воно не буде змінено.


Я думаю, що вам слід змінити послідовність echoвисловлювань. Тому що я отримуюab is not in abc
Lucio

Ти правий! : P
Едвін

Ммм .. Ні, сценарій невірний. Так я і отримую ab was found in abc, але якщо я використовую, substring=zотримуюz was found in abc
Лусіо,

1
Тепер я отримую ab is not in abc. Але z was found in abc. Це смішно: D
Lucio

1
Да! Відлуння було прямо на початку цього! XD
Edwin

47

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

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

Таким чином, ви можете використовувати цю форму щось подібне

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

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


1
Я отримую failтакі параметри:var2="abcd"
Lucio

3
@Lucio Правильно [[ $string =~ $substring ]]. Я оновив відповідь.
Ерік Карвальо


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міг би заблукати, ${foo}якщо він містить зворотні риски.


Перша версія прекрасно працює для пошуку підрядків імені монітора в списку xrandrімен моніторів, що зберігаються в змінній. +1 і ласкаво просимо в 1K представник клубу :)
WinEunuuchs2Unix

6

заява справи оболонки

Це найбільш портативне рішення, воно буде працювати навіть на старих оболонках Борна та оболонці Корна

#!/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 $@

греп

$ 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

+1 за те, що виходити за межі всіх інших. Я помітив тут і на інших сайтах обміну стеками жодна відповідь не повертає зміщення підрядки в рядку. Яка місія сьогодні ввечері :)
WinEunuuchs2Unix

@ WinEunuuchs2Unix Збираєтеся це робити в баш?
Сергій Колодяжний

Так і ні. Я роблю проект Франкенштейна, де python отримує всі метадані повідомлень gmail.com і аналізує їх, і подає список графічного інтерфейсу з детальним описом. Я знайшов відповідь , хоча тут: stackoverflow.com/questions/5031764 / ...
WinEunuuchs2Unix

@ WinEunuuchs2Unix ОК. Звучить цікаво. Я особисто вважаю за краще проаналізувати все в Python. Він має набагато більше можливостей для обробки тексту, ніж лише bash.
Сергій Колодяжний

Я знаю ваші вподобання близько двох років і поважаю їх. Але я просто вивчаю Python і змушує яда працювати всередині мене, здається, громіздко. Не кажучи вже про всю обробку масиву, з якою мені вже зручно в bash. Але принаймні я написав свій перший сценарій python, щоб висмоктати все з gmail.com google у плоский файл Linux, правда? :)
WinEunuuchs2Unix

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, але зауважте, що якщо ви перегорнете весь другий термін у подвійні лапки, він переключить тест на буквальне узгодження.

Джерело: http://tldp.org/LDP/abs/html/comppare-ops.html


4

Схожий на відповідь Едвіна, але з покращеною портативністю для 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.