Come posso annullare un test con espressioni regolari in uno script bash?


174

Usando 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 condizionalmente un percorso alla variabile PATH, se il percorso non è già presente, come in:

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 milioni di modi per farlo, ma ciò che vorrei sapere è se il condizionale può essere negato in qualche modo, come in (l'erroneo):

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

Risposte:


194

Avevi ragione, basta mettere uno spazio tra il !e il [[simileif ! [[


14
Oye vey! Proprio quando evito in modo sicuro la follia del personaggio speciale intergalattico del perl, mi ritrovo perso nello spazio bash (posizionamento)! (Sento la paura che mi stringe il fegato come un pitone.) Grazie!
David Rogers,

126

Puoi anche inserire il punto esclamativo tra parentesi:

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

ma dovresti ancorare il tuo schema per ridurre i falsi positivi:

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

che cerca una corrispondenza all'inizio o alla fine con i due punti prima o dopo di esso (o entrambi). Raccomando di usare nomi di variabili minuscole o miste come abitudine per ridurre la possibilità di collisioni di nomi con variabili shell.


Ah, grazie per il promemoria sull'ancoraggio. L'idea di usare nomi di variabili minuscole o miste è confusa per un principiante bash, poiché il consiglio che ho visto finora è di usare maiuscole. Capisco il punto che stai sollevando, ma non ho visto abbastanza esempi di scripting bash per sentirmi a mio agio con la deviazione dal mio libro di cucina.
David Rogers,

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

Trovo if [[ ! $foo =~ bar ]]più sicuro di if ! [[ $foo =~ bar ]], perché rende più facile introdurre più condizioni alif
CTodea il

19

il modo più sicuro è mettere il! per la regex negation in [[ ]]questo modo:

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

altrimenti potrebbe non funzionare su alcuni sistemi.


9

Sì, puoi annullare il test come SiegeX ha già sottolineato.

Tuttavia non dovresti usare espressioni regolari per questo - può fallire se il tuo percorso contiene caratteri speciali. Prova questo invece:

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

(Fonte)


1
Un altro motivo per utilizzare questo modulo è che non corrisponderà accidentalmente alle sottostringhe (ad esempio, non è possibile aggiungere "/ bin" al percorso perché "/ usr / bin" è già presente).
Gordon Davisson,

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

Non penso che funzionerà in modo affidabile in tutti i casi. Abbinamento regex in IMHO superiore
Felipe Alvarez

5

Mi piace semplificare il codice senza utilizzare operatori condizionali in questi casi:

TEMP=/mnt/silo/bin
[[ ${PATH} =~ ${TEMP} ]] || PATH=$PATH:$TEMP
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.