Это мой первый опыт написания 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
. Так может кто-нибудь сказать мне, в чем тут проблема?
решение1
От man 7 regex
:
Выражение в квадратных скобках представляет собой список символов, заключенных в «[]». …
… Чтобы включить литерал «-», сделайте его первым или последним символом…. [В]се другие специальные символы, включая «\», теряют свое особое значение в выражении в квадратных скобках.
Попытка выполнить регулярное выражение с помощью 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]
было бы. Вам нужно поставить your -
в конце, like [_-]
или:
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 включает в себя \
, [
, ^
, и _
.
решение2
Общее правило для регулярных выражений (и любых ошибок в больших фрагментах кода): урезайте его и перестраивайте шаг за шагом или используйте деление пополам — что вам больше подходит.
В данном случае виновником оказался символ подчеркивания — экранирование его обратной косой чертой заставило его работать.