2010-12-27 6 views
93

Utilizzando GNU bash (versione 4.0.35 (1) -release (x86_64-suse-linux-gnu), vorrei annullare un test con le espressioni regolari.Ad esempio, vorrei aggiungere un percorso al PATH condizionatamente variabile, se il percorso non è già presente, come in:Come si annulla un test con espressioni regolari in uno script bash?

TEMP=/mnt/silo/bin 
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi 
TEMP=/mnt/silo/Scripts: 
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi 
TEMP=/mnt/silo/local/bin 
if [[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH; else PATH=$PATH:$TEMP; fi 
export PATH 

sono sicuro che ci sono un milione di modi per fare questo, ma quello che vorrei sapere è se il condizionale possono essere annullati in qualche modo, come in (l'errata):!

TEMP=/mnt/silo/bin 
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi 
TEMP=/mnt/silo/Scripts: 
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi 
TEMP=/mnt/silo/local/bin 
if ![[ ${PATH} =~ ${TEMP} ]] ; then PATH=$PATH:$TEMP; fi 
export PATH 

Grazie

risposta

98

Lei aveva ragione, basta mettere uno spazio tra il ! e [[ come if ! [[

+9

Oye vey! Proprio mentre aggirgo tranquillamente la follia intergalattica del personaggio speciale di Perl, mi ritrovo perso nello spazio di bash (collocamento)! (Sento la paura stringermi la pancia come un pitone). Grazie! –

6

Sì, è possibile annullare il test come già indicato in SiegeX.

Tuttavia non è necessario utilizzare espressioni regolari per questo - può fallire se il percorso contiene caratteri speciali. Prova a modificare:

[[ ":$PATH:" != *":$1:"* ]] 

(Source)

+1

Un altro motivo per utilizzare questa forma che non corrisponderà accidentalmente sottostringhe (ad esempio, non riescono a aggiungere "/ bin" al percorso perché "/ usr/bin" è già lì). –

+0

Mi ci è voluto un po 'per capire come i due punti a sinistra mi davano l'ancoraggio che volevo. vale la pena ricordare l'idea di ridurre il pattern aggiungendo materiale alla stringa da cercare. Non capisco perché i caratteri speciali nel percorso interrompano la soluzione regex ma non la soluzione del modello bash. Puoi darmi un esempio? –

+0

Non penso che funzionerà in modo affidabile in tutti i casi. Corrispondenza Regex in IMHO superiore –

80

Si può anche mettere il punto esclamativo all'interno delle parentesi:

if [[ ! $PATH =~ $temp ]] 

ma è necessario ancorare il modello per ridurre i falsi positivi:

temp=/mnt/silo/bin 
pattern="(^|:)$temp(:|$)" 
if [[ ! $PATH =~ $pattern ]] 

che cerca una corrispondenza all'inizio o alla fine con due punti prima o dopo (o entrambi). Raccomando l'uso di nomi di variabili minuscole o maiuscole come un'abitudine per ridurre il rischio di collisioni di nomi con variabili di shell.

+0

Ah, grazie per il promemoria sull'ancoraggio. L'idea di usare nomi di lettere minuscole o miste è confusa per un principiante bash, dal momento che il consiglio che ho visto finora è quello di usare maiuscole. Capisco il punto che stai facendo, ma non ho visto abbastanza esempi di scripting bash per sentirmi a mio agio a prescindere dal mio libro di cucina. –

+3

@anyoneis si fida di noi su questo.L'uso di variabili maiuscole definite dall'utente dovrebbe essere evitato. Tutte le variabili in bash sono espanse con '$' quindi non c'è motivo di metterle in maiuscolo per farle risaltare. – SiegeX

+0

Trovo 'if [[! $ foo = ~ bar]] 'più sicuro di' if! [[$ foo = ~ bar]] ', perché rende più facile introdurre più condizioni al' se' – CTodea

15

il modo più sicuro è mettere il! per la negazione regex all'interno del [[ ]] in questo modo:

if [[ ! ${STR} =~ YOUR_REGEX ]]; then 

altrimenti potrebbe fallire su alcuni sistemi.

0

mi piace semplificare il codice senza l'utilizzo di operatori condizionali in questi casi:

TEMP=/mnt/silo/bin 
[[ ${PATH} =~ ${TEMP} ]] || PATH=$PATH:$TEMP 
Problemi correlati