Почему строковые литералы нельзя использовать в тестах регулярных выражений bash? - PullRequest
7 голосов
/ 12 июля 2011

Почему следующий скрипт bash выводит только variable worked?

#! /bin/bash

foo=baaz
regex='ba{2}z'

if [[ $foo =~ 'ba{2}z' ]]; then
    echo "literal worked"
fi

if [[ $foo =~ $regex ]]; then
    echo "variable worked"
fi

Есть ли в документации bash что-то, что оператор =~ работает только с переменными, а не с литералами? Применимо ли это ограничение к любым другим операторам?

Ответы [ 2 ]

9 голосов
/ 12 июля 2011

Вам больше не нужны кавычки для bash regex:

#! /bin/bash

foo=baaz
regex='ba{2}z'

if [[ $foo =~ ba{2}z ]]; then
    echo "literal worked"
fi

if [[ $foo =~ $regex ]]; then
    echo "variable worked"
fi

# Should output literal worked, then variable worked

Я не могу вспомнить, какая версия изменила это.

2 голосов
/ 19 апреля 2015

Ваш код работает, как и ожидалось, до Bash 3.1.Но начиная с Bash 3.2, поведение оператора сопоставления с образцом было изменено.Цитата из последнего Руководства по Bash :

«Любая часть шаблона может быть заключена в кавычки, чтобы привести его в соответствие в виде строки.«

И это именно то, что здесь происходит.Вы хотели использовать {} в качестве метасимволов, но поскольку вы цитировали его, Bash интерпретирует их буквально.У вас есть два варианта .:

1.Вы можете включить режим совместимости 3.1 с shopt -s compat31 следующим образом:

#!/bin/bash
shopt -s compat31

foo=baaz
regex='ba{2}z'

if [[ $foo =~ 'ba{2}z' ]]; then
    echo "literal worked"
fi

if [[ $foo =~ $regex ]]; then
    echo "variable worked"
fi

2.Вы можете портировать свой код, удалив цитатыс правой стороны от оператора:

#!/bin/bash

foo=baaz
regex='ba{2}z'

if [[ $foo =~ ba{2}z ]]; then
    echo "literal worked"
fi

if [[ $foo =~ $regex ]]; then
    echo "variable worked"
fi
...