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

Это мой первый сценарий 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 . Так может кто-то сказать мне, что в этом плохого?

2 Solutions collect form web for “Регулярное выражение в сценарии bash”

От 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 

Поскольку \ не является специальным, это диапазон, как и [az] . Вам нужно положить ваш - в конце, например [_-] или:

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

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

edit: Это также зависит от ваших настроек локали. Эта страница предупреждает об этом:

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

Например:

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

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

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

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

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

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

  • После перезагрузки Debian после установки
  • Переименуйте последние 8 символов в имени файла
  • BASH: массив как строковый буфер
  • Переменная как команда; eval vs bash -c
  • Предоставляет ли cron некоторые ограничения типам команд и привилегии выполнения?
  • Как написать функцию псевдонима, чтобы dd отображал индикатор выполнения?
  • Неплохо ли держать скрипты в / root?
  • назначение утилиты run-parts (8)
  • Руководство / помощь с использованием диалога с bash-скриптами
  • Как определить среду рабочего стола в сценарии bash?
  • Замена обратной косой черты запятыми в Bash
  • Linux и Unix - лучшая ОС в мире.