2015-05-22 3 views
3

Я ищу регулярное выражение BASH, чтобы вытащить «db» agruments из приведенных ниже команд. Однако порядок аргументов не гарантируется. По какой-то причине я не могу заставить его работать полностью.Regex соответствует концу строки

То, что я до сих пор

regex="--db (.*)($| --)" 
[[ [email protected] =~ $regex ]] 
DB_NAMES="${BASH_REMATCH[1]}" 

# These are example lines 
somecommand --db myDB --conf /var/home # should get "myDB" 
somecommand --db myDB anotherDB manymoreDB --conf /home # should get "myDB anotherDB manymoreDB" 
somecommand --db myDB # should get "myDB" 
somecommand --db myDB anotherDB # should get "myDB anotherDB" 

Любое предложение на регулярное выражение?

+0

Я не думаю, что bash поддерживает не жадный матч. вы можете попробовать либо '([^ -] *)' вместо '(. *)', либо использовать awk или sed – Fabricator

+0

Почему бы не использовать 'getopt' или' getopts' для синтаксического анализа аргументов командной строки? – nanoix9

ответ

4

Проблема заключается в том, что bash использует аромат regex, который не включает в себя нежадные оператор повторения (*?, +?). Потому что * жадный и нет способа сказать, чтобы он не был жадным, первое подвыражение в скобках ((.*)) соответствует всем до конца строки.

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

Например, если значения после --db не содержат дефис (-), вы можете использовать этот regex:

regex='--db ([^-]*)($| --)' 

Это соответствует всем примерам, размещенным в этом вопросе.

1

По умолчанию RegEx пытается получить максимально возможное количество совпадений, используйте неживой код (ленивый). Вы также можете поставить -- первый поэтому двигатель будет использовать, что первый

--db[[:space:]](.*?)([[:space:]]--|$) 

Demo


Если вы не хотите --, вы можете использовать не захватить группу

--db[[:space:]](.*?)(?:[[:space:]]--|$) 
        ^^ Notice the ?: 

Demo

+1

Bash не поддерживает не жадные. –

+2

Bash не поддерживает группы без захвата. – axiac

0

Я думаю, что вы хотите совпадать с без пробела, чтобы поймать первую группу:

regex="--db (\S+)(--|$)" 
+0

bash не использует классы символов с '\ S' - хотя вы не можете указывать правильное выражение. –

2

следующие работы:

regex="--db[[:space:]]([[:alnum:][:space:]]+)([[:space:]]--|$)" 
[[ "[email protected]" =~ $regex ]] 

Там были два вопроса:

  1. Символьные классы, такие как [: пространство:] должно быть используемый для представления пробелов
  2. (.*) жадный и дойдет до вашего последнего -- буквального. Поскольку bash не поддерживает не-жадное соответствие, мы должны сопоставлять [[:alnum:][:space:]], что гарантирует, что мы остановимся на следующем --.
+0

Это не работает для первых двух примеров в вопросе. – axiac

+0

@axiac - ах, я предположил, что RegEx был прав, и цитаты вызывают проблему. Исправлено регулярное выражение, спасибо. –

+0

Котировки не навредят. Я запустил код, размещенный в вопросе, и он работает для последних двух примеров. Проблема заключается в первых двух, потому что 'regex', используемые' bash', являются жадными, и я не мог найти никакого способа (в документации) сделать их не-жадными. – axiac

Смежные вопросы