Bash = ~ regex і https://regex101.com/


12

Використовуючи https://regex101.com/, я створив регулярний вираз, щоб повернути перше виникнення IP-адреси в рядку.

RegExp:

(?:\d{1,3}\.)+(?:\d{1,3})

RegExp, включаючи роздільники:

/(?:\d{1,3}\.)+(?:\d{1,3})/

За допомогою наступної тестової рядки:

eu-west                       140.243.64.99 

Він повертає повну відповідність:

140.243.64.99

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

temp="eu-west                       140.243.64.99            "
regexp="(?:\d{1,3}\.)+(?:\d{1,3})"
if [[ $temp =~ $regexp ]]; then
  echo "found a match"
else
  echo "No IP address returned"
fi

3
Це схоже на регулярний вираз Perl для мене. Баш цього не підтримує.
Кусалаланда

1
=~Оператор обговорюється тут в керівництві , де це написано Баш використовує «розширені регулярні вирази». Розширені реджекси описані на regex(7)сторінці man і коротко узагальнені тут .
glenn jackman

Відповіді:


15

\d- це нестандартний спосіб сказати "будь-яку цифру". Я думаю, що це походить від Perl, і багато інших мов та утиліт підтримують і Perl-сумісні RE (PCRE). (наприклад, GNU grep 2.27 в розтягуванні Debian підтримує аналогічні \wдля символів слова навіть у звичайному режимі.)

\dХоча Bash не підтримує , тому вам потрібно явно використовувати [0-9]або [[:digit:]]. Те ж саме для групи, що не захоплює (?:..), використовуйте просто (..)замість цього.

Це має надрукувати match:

temp="eu-west                       140.243.64.99            "
regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
[[ $temp =~ $regexp ]] && echo match

2
Чи grepпідтримує ваш GNU \dбез -P?
Стефан Шазелас

@ StéphaneChazelas, ну, звичайно, ні. Це підтримує \wі про \bщо я дізнався від Perl, тому я заплутався в цьому.
ilkkachu

1
не дуже чесно сказати, \dабо PCRE "нестандартні". Вони досить стандартні, просто відрізняються від оригінальних регулярних виразів і розширених регулярних виразів.
Даніель Фаррелл

1
@DanielFarrell, стандарт у цьому випадку - це те, що вказує POSIX , і про нього не відомо \d. Хоча ви маєте рацію в тому, що PCRE є досить стандартними або, як мінімум, чітко визначеними. Дратує проблема в тому , що GNU Grep (або Glibc) підтримує деякі PCRE-атомів, по крайней мере , \wі \sпри інтерпретації ERE, і в цьому контексті вони дуже є нестандартними. Моє фразування може частково випливати з цього, і неправильне зібрання, яке \dпідтримувалося GNU.
ilkkachu

4

(:...)і \dє операторами регулярної експресії perl або PCRE (наприклад, у GNU grep -P).

bashпідтримує лише розширені регулярні вирази, як, за grep -Eвинятком того, що для регулярних виразів, що передаються буквально на [[ text =~ regexp-here ]]відміну від результатів розширення без котирування (як у [[ text =~ $var ]]або [[ test =~ $(printf '%s\n' 'regexp-here') ]]), він обмежений набором функцій POSIX розширеного регулярного вираження.

Тож навіть у системах, де це grep -E '\d'буде працювати (GNU ERE вже імпортували деякі розширення з реггексів perl, як, наприклад, \sмайбутні версії \d), вам доведеться використовувати:

regexp='\d'
[[ $text =~ $regexp ]]

в тому, bashщоб він працював ( [[ $text =~ \d ]]не буде).

Для оболонки, яка підтримує PCRE, ви можете zshзамість цього використовувати :

set -o rematchpcre
[[ $text =~ '(?:\d{1,3}\.)+(?:\d{1,3})' ]]

ksh93 також підтримує власну реалізацію perl-подібних регулярних виразів (не повністю сумісних) як частини відповідності шаблону. Там ви використовуєте:

regexp='~(P)(?:\d{1,3}\.)+(?:\d{1,3})'
[[ $text = $regexp ]]

(зауважте =замість цього =~. Ви хочете використовувати тимчасові змінні, оскільки це дуже баггі, коли ви цього не робите)


1

Сайт regex101.com використовує PCRE (дивіться у верхньому лівому куті) як за замовчуванням, і йому не вистачає підтримки синтаксису "Extended". Це "Сумісні регулярні вирази Perl", які надходять (як розумно очікувати) від Perl.

PCRE підтримується деякими інструментами (на зразок grep -P) за певних умов, але підтримка bashe regex всередині [[…]]ідіоми призначена лише для розширеного регулярного вираження (наприклад grep -E).

У розширеному регулярному вираженні (?…)дужок, що не захоплюють , не існує, і \ d також відсутній. Вам потрібно використовувати прості (…)та [0-9]:

regexp="([0-9]{1,3}\.)+([0-9]{1,3})"
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.