Как избежать шаблонов расширенных путей в выражениях в кавычках? - PullRequest
4 голосов
/ 09 февраля 2009

В дополнение к базовым шаблонам *, ? и [...] оболочка Bash предоставляет расширенные операторы сопоставления с образцом, такие как !(pattern-list) («сопоставлять все, кроме одного из заданных шаблонов»). Для их использования необходимо установить параметр оболочки extglob. Пример:

~$ mkdir test ; cd test ; touch file1 file2 file3
~/test$ echo *
file1 file2 file3
~/test$ shopt -s extglob  # make sure extglob is set
~/test$ echo !(file2)
file1 file3

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

~/test$ cd ..
~$ bash -c "cd test ; echo *"
file1 file2 file3
~$ bash -c "cd test ; echo !(file2)"  # expected output: file1 file3
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `cd test ; echo !(file2)'

Я пробовал все виды побега, но ничего из того, что я придумал, не сработало правильно. Я также подозревал, что extglob не установлен в под-оболочке, но это не так:

~$ bash -c "shopt -s extglob ; cd test ; echo !(file2)"
bash: -c: line 0: syntax error near unexpected token `('
bash: -c: line 0: `cd test ; echo !(file2)'

Любое решение приветствуется!

Ответы [ 4 ]

4 голосов
/ 12 августа 2010

bash анализирует каждую строку перед ее выполнением, поэтому «shopt -s extglob» не будет действовать, когда bash проверяет синтаксис шаблона смещения. Опция не может быть включена в той же строке. Вот почему решение "bash -O extglob -c 'xyz'" (от Randy Proctor) работает и является обязательным.

3 голосов
/ 09 февраля 2009
$ bash -O extglob -c 'echo !(file2)'
file1 file3
3 голосов
/ 05 июня 2009

Вот еще один способ, если вы хотите избежать eval и вам нужно включить или выключить extglob в подоболочке. Просто поместите ваш шаблон в переменную:

bash -c 'shopt -s extglob; cd test; patt="!(file2)"; echo $patt; shopt -u extglob; echo $patt'

дает этот вывод:

file1 file3
!(file2)

демонстрирует, что extglob был установлен и не установлен. Если бы первый echo имел кавычки вокруг $patt, он просто выплюнул бы образец, как второй echo (который, вероятно, должен иметь кавычки).

1 голос
/ 09 февраля 2009

Ну, у меня нет никакого реального опыта с extglob , но я могу заставить его работать, обернув echo в eval:

$ bash -c 'shopt -s extglob ; cd  test ; eval "echo !(file2)"'
file1 file3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...