Тест Баша: що робить "= ~"?


40
#!/bin/bash
INT=-5

if [[ "$INT" =~ ^-?[0-9]+$ ]]; then

echo "INT is an integer."

else

echo "INT is not an integer." >&2

exit 1

fi

Що робить провідний ~у вихідному регулярному виразі?



5
Ви читали посібник з bash? Що вам здається незрозумілим?
ікар

3
Шукайте на баш-man man сторінці = ~
Jeff Schaller

Відповіді:


46

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

[[ "string" =~ pattern ]]

Зауважте, що рядок слід цитувати, а регулярний вираз не повинен цитувати.

Аналогічний оператор використовується в мові програмування Perl.

Регулярні вирази, що розуміються, bashтакі ж, як і GNU, які grepрозуміють із -Eпрапором, тобто розширений набір регулярних виразів.


Дещо поза темою, але добре знати:

При зіставленні з регулярним виразом, що містить групи захоплення, частина рядка, захоплена кожною групою, доступна в BASH_REMATCHмасиві. Нульовий / перший запис у цьому масиві відповідає &шаблону заміни команди sed"заміщення" (або $&в Perl), що є бітом рядка, що відповідає шаблону, тоді як записи в індексі 1 і далі відповідають \1, \2і т.д. . в sedшаблоні заміни (або $1, і $2т.д. в Perl), тобто біти збігаються кожної дужкою.

Приклад:

string=$( date +%T )

if [[ "$string" =~ ^([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$ ]]; then
  printf 'Got %s, %s and %s\n' \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
fi

Це може вивести

Got 09, 19 and 14

якщо поточний час стане 09:19:14.

REMATCHБіт BASH_REMATCHімені масиву походить від «регулярного виразу», тобто «RE-Match».


У не- bashBourne-подібних оболонках можна також використовувати exprобмежене регулярне узгодження виразів (використовуючи лише основні регулярні вирази).

Невеликий приклад:

$ string="hello 123 world"
$ expr "$string" : ".*[^0-9]\([0-9][0-9]*\)"
123

2
Це те саме, що grep -Eрозуміється лише в системах GNU і тільки при використанні змінної без котирування в якості шаблону [[ $var = $pattern ]](див. [[ 'a b' =~ a\sb ]]Vs p='a\sb'; [[ 'a b' =~ $p ]]). Також майте на увазі, що котирування оболонки впливає на значення RE-операторів і що деякі символи повинні бути цитовані для маркування оболонки, яке може вплинути на обробку RE. [[ '\' =~ [\/] ]]повертає помилкове. ksh93має ще гірші проблеми. Дивіться zsh(або bash 3.1) для більш безпечного підходу, коли цитування оболонки та RE чітко розділені. [Вбудований в zshа yashтакож =~оператор.
Стефан Шазелас

2
дуже круто off-topic! +1 (
JJoao

@ StéphaneChazelas Як "безпечніше", що обидва цього матчу в zsh ?: [[ "This is a fine mess." =~ T.........fin*es* ]]; [[ "This is a fine mess." =~ T.........fin\*es\* ]]. Або що цитується *також збігається? [[ "This is a fine mess." =~ "T.........fin*es*" ]].
соронтар

Це безпечніше (IMO), оскільки це набагато простіші правила. Цитування оболонок та втеча із РЕ явно роздільні. В [[ a =~ .* ]]або [[ a =~ '.*' ]]або [[ a =~ \.\* ]], то ж .*RE передається =~оператору. ДЕЙ, в bash, [[ '\' =~ [)] ]]повертає помилку, чи знаєте ви, не намагаючись це [[ '\' =~ [\)] ]]відповідати? Як щодо [[ '\' =~ [\/] ]](це в ksh93). Як щодо c='a-z'; [[ a =~ ["$c"] ]](порівняйте з =оператором)? Дивіться також: [[ '\' =~ [^]"."] ]]який повертає помилкове ... Зверніть увагу , що ви можете зробити shopt -s compat31в , bashщоб отримати zshповедінку.
Стефан Шазелас

zsh/ bash -o compat31'поведінка для [[ a =~ '.*' ]]також відповідає [ a '=~' '.*' ](для [реалізацій, які підтримують =~) або expr a : '.*'. OTOH, це не відповідає [[ a = '*' ]]vs [[ a = * ]](але тоді, глобуси є частиною мови оболонки, тоді як RE - ні).
Стефан Шазелас

4

Ви повинні прочитати сторінки bash man під [[ expression ]]розділом.

An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3)).

Коротше кажучи, =~це оператор, як ==і !=. Це не має нічого спільного з фактичним регулярним виразом у рядку праворуч.


Чи можете ви придумати кілька прикладів, що демонструють використання =~в реальному житті ...?
Джордж Васильоу

1
@GeorgeVasiliou Я досить часто його використовую в сценаріях, які переводять вихідну команду в змінну. Потім змінна перевіряється, чи відповідає вона деякому рядковому шаблону. Це корисно, наприклад, якщо ви хочете виконати певні дії, виходячи з деякого виводу помилки з цієї команди.
Майкл Мартінес

@Sokel Для деяких "RTFM" простіше сказати, ніж зробити. ⋯ man [[ expresssion ]]ні і man [[повернення нічого. help [[повертає корисну інформацію - починаючи [[з внутрішньої команди bash - але не говорить про те, =~використовує базовий чи розширений синтаксис регулярних виразів. ⋯ Текст, який ви цитуєте, зі сторінки bash man. Я усвідомлюю, що ви сказали «читайте сторінки bash man», але спочатку я подумав, що ви маєте на увазі прочитати сторінки чоловіка в bash. У будь-якому випадку, man bashповертає величезний файл, протяжністю 4139 рядків (72 сторінки). У ньому можна шукати натисканням /▒▒▒, яке займає регулярний вираз, аромат якого - як-от =~- не вказано.
Алекс Квінн
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.