Pergunta

Além dos padrões básicos *, ? e [...], o shell Bash fornece operadores padrão correspondentes estendidas como !(pattern-list) ( "corresponder a todos, exceto um dos padrões dados"). A opção shell extglob precisa ser configurado para usá-los. Um exemplo:

~$ 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

Se eu passar uma expressão de shell para um programa que executa-lo em um sub-shell, o operador provoca um erro. Aqui está um teste que dirige uma sub-shell diretamente (aqui eu estou executando a partir de outro diretório para se certificar de expansão não acontece prematuramente):

~/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)'

Eu tentei todos os tipos de escapar, mas nada que eu vim acima com funcionou corretamente. Eu também suspeito extglob não está definido em uma sub-shell, mas isso não é o caso:

~$ 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)'

Qualquer solução apreciada!

Foi útil?

Solução

$ bash -O extglob -c 'echo !(file2)'
file1 file3

Outras dicas

festa analisa cada linha antes de executá-lo, por isso "extglob shopt -s" não ter tido efeito quando o bash é validar a sintaxe padrão de englobamento. A opção não pode ser ativado na mesma linha. É por isso que a solução "bash -O extglob -c 'xyz'" (do Randy Proctor) funciona e é necessário.

Aqui está outra maneira, se você quiser evitar eval e você precisa ser capaz de transformar extglob e desligar dentro do subnível. Basta colocar o seu padrão em uma variável:

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

dá essa saída:

file1 file3
!(file2)

demonstrando que extglob foi activar e desactivar. Se o primeiro echo tinha aspas em torno do $patt, seria apenas cuspir o padrão como o segundo echo (que provavelmente deve ter aspas).

Bem, eu não tenho nenhuma experimentar real com extglob , mas eu posso obtê-lo para o trabalho envolvendo a echo em uma eval:

$ bash -c 'shopt -s extglob ; cd  test ; eval "echo !(file2)"'
file1 file3
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top