Domanda

In aggiunta ai modelli di base *, ? e [...], la shell Bash fornisce modello esteso corrispondenza operatori come !(pattern-list) ( "corrispondenti tutti tranne uno dei pattern dati"). L'opzione di shell extglob deve essere impostato per usarli. Un esempio:

~$ 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 passo un'espressione shell di un programma che esegue in una sotto-shell, l'operatore causa un errore. Ecco un test che viene eseguito direttamente un sub-shell (qui sto eseguendo da un'altra directory per assicurarsi che l'espansione non accade 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)'

Ho provato tutti i tipi di fuggire, ma niente mi è venuta in mente ha funzionato correttamente. Ho anche sospettato extglob non è impostato in una sotto-shell, ma non è questo il 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)'

Qualsiasi soluzione apprezzato!

È stato utile?

Soluzione

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

Altri suggerimenti

bash analizza ogni riga prima di eseguirlo, così "shopt -s extglob" non hanno avuto effetto quando bash sta convalidando la sintassi modello globbing. L'opzione non può essere attivata sulla stessa linea. Ecco perché la soluzione "bash -O extglob -c 'xyz'" (da Randy Proctor) funziona ed è necessario.

Ecco un altro modo, se si vuole evitare eval ed è necessario essere in grado di trasformare extglob e spegnimento all'interno della subshell. Basta mettere il vostro modello in una variabile:

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

dà questo output:

file1 file3
!(file2)

extglob è stata inserita o disinserita. Se il primo ha avuto echo citazioni intorno al $patt, sarebbe solo sputare il modello come la seconda echo (che probabilmente dovrebbe avere le virgolette).

Beh, non ho alcuna vera experince con extglob , ma posso farlo funzionare avvolgendo il echo in un eval:

$ bash -c 'shopt -s extglob ; cd  test ; eval "echo !(file2)"'
file1 file3
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top