Поиск подстроки без учета регистра в скрипте оболочки

Как я могу написать сценарий оболочки, который будет делать нестандартное подстрочное совпадение вывода команды?

Прежде всего, это простой пример сценария, который не игнорирует случай:

 #!/bin/bash if [ $(echo hello) == hello ]; then echo it works fi 

Попробуйте изменить строку hello справа, и она больше не it works эхом. Попробуйте заменить echo hello командой по вашему выбору. Если вы хотите игнорировать регистр, и ни одна строка не содержит разрыв строки, вы можете использовать grep:

 #!/bin/bash if echo Hello | grep -iqF hello; then echo it works fi 

Ключевым моментом здесь является то, что вы передаете командный вывод в grep . Оператор if проверяет состояние выхода самой правой команды в конвейере – в этом случае grep. Grep выходит с успехом тогда и только тогда, когда находит совпадение.

Опция -i grep говорит игнорировать регистр.
Опция -q говорит, что не выдавать выход и выйти после первого совпадения.
Опция -F говорит, что аргумент рассматривается как строка, а не регулярное выражение.

Обратите внимание, что в первом примере используется [ expression ] которое позволяет проводить прямые сравнения и различные полезные операторы. Вторая форма просто выполняет команды и проверяет их статус выхода.

Вы можете использовать подстроку, не nocasematch в nocasematch в bash с помощью оператора регулярного выражения =~ если вы установите nocasematch оболочки nocasematch . Например

 s1="hElLo WoRlD" s2="LO" shopt -s nocasematch [[ $s1 =~ $s2 ]] && echo "match" || echo "no match" match s1="gOoDbYe WoRlD" [[ $s1 =~ $s2 ]] && echo "match" || echo "no match" no match 

Для строчного поиска по регистру значения переменной needle в значении переменной haystack :

 case "$haystack" in *"$needle"*) echo "present"; *) echo "absent"; esac 

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

 uc_needle=$(printf %s "$needle" | tr '[:lower:]' '[:upper:]' ; echo .); uc_needle=${uc_needle%.} uc_haystack=$(printf %s "$haystack" | tr '[:lower:]' '[:upper:]' ; echo .); uc_haystack=${uc_haystack%.} case "$uc_haystack" in *"$uc_needle"*) echo "present";; *) echo "absent";; esac 

Обратите внимание, что tr в GNU coreutils не поддерживает многобайтовые локали (например, UTF-8). Чтобы выполнить работу с многобайтовыми локалями, вместо этого используйте awk. Если вы собираетесь использовать awk, вы можете сделать это для сравнения строк, а не просто для преобразования.

 if awk 'BEGIN {exit !index(toupper(ARGV[2]), toupper(ARGV[1]))}' "$needle" "$haystack"; then echo "present" else echo "absent" fi 

tr из BusyBox не поддерживает синтаксис [: CLASS :] ; вы можете использовать tr az AZ . BusyBox не поддерживает не-ASCII-локали.

В bash (но не sh) существует встроенный синтаксис для преобразования case и более простой синтаксис для сопоставления строк.

 if [[ "${haystack^^}" = *"${needle^^}"* ]]; then echo "present" else echo "absent" esac