Регулярное выражение в скрипте bash

13

Это мой первый раз, когда я использую bash-скрипты, поэтому я, вероятно, делаю легкую ошибку.

По сути, я пытаюсь написать сценарий, который получает группы пользователей, и, если они находятся в определенной группе, он будет регистрировать это соответствующим образом. Очевидно, будет больше функциональности, но нет смысла строить это, когда я даже не могу заставить работать регулярное выражение!

Пока у меня есть это:

#!/bin/bash

regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"

# example output
groups="username : username usergroup"

echo "$groups" >> /home/jrdn/log

if [[ "$groups" =~ $regex ]]; then
    echo "Match!" >> /home/jrdn/log
else
    echo "No match" >> /home/jrdn/log
fi

В каждом месте, где я пробовал это регулярное выражение, это работает. Но в скрипте bash он только выводит $groups, а затем No match. Так может кто-нибудь сказать мне, что с ним не так?

jrdn
источник
1
Что заставляет вас думать, что с этим что-то не так?
manatwork
1
@jrdnhannah, затем попытайтесь медленно воссоздать целевое регулярное выражение, сначала сопоставьте, ^([a-zA-Z0-9\-_]+)затем добавьте двоеточие и так далее ... вы должны довольно скоро выяснить, в чем проблема.
Петер
2
То же самое здесь с Bash 4.2.45. Избегание подчеркивания исправило это. Weird. @ jrdnhannah не могли бы вы написать это как ответ и принять это, пожалуйста?
Тердон
1
Поскольку я только что зарегистрировался в Unix SE, мне нужно подождать 8 часов, прежде чем ответить на мой собственный. Рад отметить это как ответ, если кто-то другой, хотя.
13
4
@terdon bash, вероятно, просто вызывает регулярные выражения libc. Так что это зависит от версии libc, а не от версии bash. Посмотрите мой ответ ... (Или, может быть, даже на последовательности сортировки, которую вы используете)
Дероберт

Ответы:

14

От man 7 regex:

Выражение в скобках - это список символов, заключенных в «[]». ...

… Чтобы включить буквальное «-», сделайте его первым или последним символом…. [A] Все другие специальные символы, включая '\', теряют свое особое значение в выражении в скобках.

Попытка регулярного выражения с egrep дает ошибку:

$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end

Вот более простая версия, которая также выдает ошибку:

$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end

Так \как не является особенным, это диапазон, как [a-z]хотелось бы. Вы должны поставить свой -в конце, как [_-]или:

echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup

Это должно работать независимо от вашей версии libc (в egrep или bash).

изменить: это на самом деле зависит от ваших настроек локали тоже. Руководство действительно предупреждает об этом:

Диапазоны очень зависят от последовательности сортировки, и переносимые программы не должны полагаться на них.

Например:

$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'
\_

Конечно, даже если это не ошибка, он не делает то, что вы хотите:

$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'
\^_

Это диапазон, который в ASCII, включает в себя \, [, ^, и _.

derobert
источник
Интересный. Мой не egrepдает ошибки, просто соответствует правильно.
manatwork
@manatwork ваша последовательность сопоставления, вероятно, позволяет диапазон ....
Дероберт
Я не знаю много о сопоставлении. Вы имеете в виду это: LC_COLLATE="en_US.UTF-8"?
manatwork
@manatwork Я отредактировал вопрос, чтобы привести пример. Обратите внимание, что в вашей системе это может отличаться, потому что иногда эти последовательности сортировки (сортировки) меняются.
Дероберт
1
@manatwork Все хорошо, я чуть не подал отчет об ошибке, прежде чем заметил попытку сбежать -...
Дероберт
4

Общее правило с регулярными выражениями (и любыми ошибками в больших кусках кода): сокращайте его и перестраивайте его шаг за шагом или используйте разделение на части - все, что работает лучше для вас.

В этом случае виновником оказалось подчеркивание - выход из него с обратной косой чертой заставил его работать.

peterph
источник