bash регулярне вираження з лапками?


77

Наступний код

number=1
if [[ $number =~ [0-9] ]]
then
  echo matched
fi

робіт. Однак, якщо я намагаюся використовувати лапки в регулярному виразі, це зупиняється:

number=1
if [[ $number =~ "[0-9]" ]]
then
  echo matched
fi

Я "\[0-9\]"теж пробував . Чого мені не вистачає?

Як не дивно, передовий посібник із сценаріїв bash пропонує, що це має спрацювати.

Версія Bash 3.2.39.


4
АБС досить відомий як джерело неточних (або, в кращі дні, просто оманливих) вказівок; вважайте це W3Schools сценаріїв оболонки. Розгляньте bash-hackers.org або wooledge wiki як альтернативи, що підтримуються з огляду на точність.
Чарльз Даффі

Відповіді:


116

Його змінили між 3.1 та 3.2 . Думаю, розширений путівник потребує оновлення.

Це стислий опис нових функцій, доданих до bash-3.2 з моменту випуску bash-3.1. Як завжди, сторінка керівництва (doc / bash.1) - це місце для пошуку повних описів.

  1. Нові можливості в Bash

відрізати

f. Цитування аргументу рядка оператору [[command's = ~] тепер змушує збіг рядків, як і з іншими операторами збігу шаблонів.

На жаль, це порушить існуючі цитати за допомогою сценаріїв, якщо у вас не було розуміння зберігати шаблони у змінних та використовувати їх замість регулярних виразів. Приклад нижче.

$ bash --version
GNU bash, version 3.2.39(1)-release (i486-pc-linux-gnu)
Copyright (C) 2007 Free Software Foundation, Inc.
$ number=2
$ if [[ $number =~ "[0-9]" ]]; then echo match; fi
$ if [[ $number =~ [0-9] ]]; then echo match; fi
match
$ re="[0-9]"
$ if [[ $number =~ $re ]]; then echo MATCH; fi
MATCH

$ bash --version
GNU bash, version 3.00.0(1)-release (i586-suse-linux)
Copyright (C) 2004 Free Software Foundation, Inc.
$ number=2
$ if [[ $number =~ "[0-9]" ]]; then echo match; fi
match
$ if [[ "$number" =~ [0-9] ]]; then echo match; fi
match

17
Це справжня забава. Котирувані регулярні вирази більше не працюють. Регулярні вирази без котирувань із пробілами не працюють. Регулярні вирази на основі змінних працюють, навіть якщо вони містять пробіли. Який безлад.
Павло Шимерда,

21

Bash 3.2 представив параметр сумісності compat31, який повертає поведінку цитування регулярних виразів bash до 3.1

Без compat31:

$ shopt -u compat31
$ shopt compat31
compat31        off
$ set -x
$ if [[ "9" =~ "[0-9]" ]]; then echo match; else echo no match; fi
+ [[ 9 =~ \[0-9] ]]
+ echo no match
no match

З compat31:

$ shopt -s compat31
+ shopt -s compat31
$ if [[ "9" =~ "[0-9]" ]]; then echo match; else echo no match; fi
+ [[ 9 =~ [0-9] ]]
+ echo match
match

Посилання на патч: http://ftp.gnu.org/gnu/bash/bash-3.2-patches/bash32-039


7

GNU bash, версія 4.2.25 (1) -випуск (x86_64-pc-linux-gnu)

Деякі приклади відповідності рядків та регулярних виразів

    $ if [[ 234 =~ "[0-9]" ]]; then echo matches;  fi # string match
    $ 

    $ if [[ 234 =~ [0-9] ]]; then echo matches;  fi # regex natch 
    matches


    $ var="[0-9]"

    $ if [[ 234 =~ $var ]]; then echo matches;  fi # regex match
    matches


    $ if [[ 234 =~ "$var" ]]; then echo matches;  fi # string match after substituting $var as [0-9]

    $ if [[ 'rss$var919' =~ "$var" ]]; then echo matches;  fi   # string match after substituting $var as [0-9]

    $ if [[ 'rss$var919' =~ $var ]]; then echo matches;  fi # regex match after substituting $var as [0-9]
    matches


    $ if [[ "rss\$var919" =~ "$var" ]]; then echo matches;  fi # string match won't work

    $ if [[ "rss\\$var919" =~ "$var" ]]; then echo matches;  fi # string match won't work


    $ if [[ "rss'$var'""919" =~ "$var" ]]; then echo matches;  fi # $var is substituted on LHS & RHS and then string match happens 
    matches

    $ if [[ 'rss$var919' =~ "\$var" ]]; then echo matches;  fi # string match !
    matches



    $ if [[ 'rss$var919' =~ "$var" ]]; then echo matches;  fi # string match failed
    $ 

    $ if [[ 'rss$var919' =~ '$var' ]]; then echo matches;  fi # string match
    matches



    $ echo $var
    [0-9]

    $ 

    $ if [[ abc123def =~ "[0-9]" ]]; then echo matches;  fi

    $ if [[ abc123def =~ [0-9] ]]; then echo matches;  fi
    matches

    $ if [[ 'rss$var919' =~ '$var' ]]; then echo matches;  fi # string match due to single quotes on RHS $var matches $var
    matches


    $ if [[ 'rss$var919' =~ $var ]]; then echo matches;  fi # Regex match 
    matches
    $ if [[ 'rss$var' =~ $var ]]; then echo matches;  fi # Above e.g. really is regex match and not string match
    $


    $ if [[ 'rss$var919[0-9]' =~ "$var" ]]; then echo matches;  fi # string match RHS substituted and then matched
    matches

    $ if [[ 'rss$var919' =~ "'$var'" ]]; then echo matches;  fi # trying to string match '$var' fails


    $ if [[ '$var' =~ "'$var'" ]]; then echo matches;  fi # string match still fails as single quotes are omitted on RHS 

    $ if [[ \'$var\' =~ "'$var'" ]]; then echo matches;  fi # this string match works as single quotes are included now on RHS
    matches

5

Як зазначалося в інших відповідях, введення регулярного виразу у змінну є загальним способом досягнення сумісності між різними версії. Ви також можете використовувати цей обхідний шлях, щоб досягти того самого, зберігаючи регулярний вираз у умовному виразі:

$ number=1
$ if [[ $number =~ $(echo "[0-9]") ]]; then echo matched; fi
matched
$ 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.