использовать регулярное выражение в if-условии в bash - PullRequest
83 голосов
/ 27 февраля 2010

Мне интересно общее правило использования регулярного выражения в предложении if в bash?

Вот пример

$ gg=svm-grid-ch  
$ if [[ $gg == *grid* ]] ; then echo $gg; fi  
svm-grid-ch  
$ if [[ $gg == ^....grid* ]] ; then echo $gg; fi  
$ if [[ $gg == ....grid* ]] ; then echo $gg; fi  
$ if [[ $gg == s...grid* ]] ; then echo $gg; fi  
$   

Почему последние три не совпадают?

Надеюсь, вы могли бы дать как можно больше общих правил, не только для этого примера.

Ответы [ 5 ]

120 голосов
/ 27 февраля 2010

При использовании шаблона glob знак вопроса представляет отдельный символ, а звездочка - последовательность из нуля или более символов:

if [[ $gg == ????grid* ]] ; then echo $gg; fi

При использовании регулярного выражения точка представляет отдельный символ, а звездочка - ноль или более предшествующего символа. Таким образом, «.*» представляет ноль или более любого символа, «a*» представляет ноль или более «a», «[0-9]*» представляет ноль или более цифр. Другим полезным (среди многих) является знак плюс, который представляет один или несколько предшествующих символов. Так что «[a-z]+» представляет один или несколько строчных букв (в локали C и некоторых других).

if [[ $gg =~ ^....grid.*$ ]] ; then echo $gg; fi
35 голосов
/ 27 февраля 2010

Использование = ~

для проверки регулярных выражений Руководство по регулярным выражениям Оглавление

13 голосов
/ 27 февраля 2010
if [[ $gg =~ ^....grid.* ]]
7 голосов
/ 28 февраля 2010

Добавление этого решения с grep и базовыми sh встроенными функциями для тех, кто заинтересован в более портативном решении (независимо от версии bash; также работает с простым старым sh, на платформах, отличных от Linux и т. 1005 *

# GLOB matching
gg=svm-grid-ch    
case "$gg" in
   *grid*) echo $gg ;;
esac

# REGEXP    
if echo "$gg" | grep '^....grid*' >/dev/null ; then echo $gg ; fi    
if echo "$gg" | grep '....grid*' >/dev/null ; then echo $gg ; fi    
if echo "$gg" | grep 's...grid*' >/dev/null ; then echo $gg ; fi    

# Extended REGEXP
if echo "$gg" | egrep '(^....grid*|....grid*|s...grid*)' >/dev/null ; then
  echo $gg
fi    

Некоторые воплощения grep также поддерживают опцию -q (тихий) в качестве альтернативы перенаправлению на /dev/null, но перенаправление опять-таки является наиболее переносимым.

3 голосов
/ 28 февраля 2010

@ OP

Используется ли glob pettern не только для имен файлов?

Нет, шаблон "glob" используется не только для имен файлов. Вы используете его для сравнения строк. В ваших примерах вы можете использовать case / esac для поиска шаблонов строк.

 gg=svm-grid-ch 
 # looking for the word "grid" in the string $gg
 case "$gg" in
    *grid* ) echo "found";;
 esac

 # [[ $gg =~ ^....grid* ]]
 case "$gg" in ????grid*) echo "found";; esac 

 # [[ $gg =~ s...grid* ]]
 case "$gg" in s???grid*) echo "found";; esac

В bash, когда использовать шаблон glob и когда использовать регулярное выражение? Спасибо!

Regex более универсален и «удобен», чем «шаблоны глобов», однако, если вы не выполняете сложные задачи, которые «глобализация / расширенное глобирование» не может обеспечить легко, то нет необходимости использовать регулярные выражения. Regex не поддерживаются для версии bash <3.2 (как упоминалось Денисом), но вы все равно можете использовать расширенную глобализацию (установив <code>extglob). для расширенного сглаживания см. здесь и несколько простых примеров здесь .

Обновление для OP: Пример поиска файлов, начинающихся с 2 символов (точки "." Означают 1 символ), за которыми следует "g" с использованием регулярного выражения

например, вывод

$ shopt -s dotglob
$ ls -1 *
abg
degree
..g

$ for file in *; do [[ $file =~ "..g" ]] && echo $file ; done
abg
degree
..g

В приведенном выше примере файлы сопоставляются, поскольку их имена содержат 2 символа, за которыми следует «g». (т.е. ..g).

Эквивалент с globbing будет примерно таким: (посмотрите на reference для значений ? и *)

$ for file in ??g*; do echo $file; done
abg
degree
..g
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...