Corrispondenza di Regex in una dichiarazione di Bash if

Cosa ho fatto di sbagliato qui?

Cercando di abbinare qualsiasi stringa che contenga spazi, lettere minuscole, maiuscole o numeri. Anche personaggi speciali sarebbero belli, ma penso che sia necessario sfuggire a certi personaggi.

TEST="THIS is a TEST title with some numbers 12345 and special char *&^%$#" if [[ "$TEST" =~ [^a-zA-Z0-9\ ] ]]; then BLAH; fi 

Questo ovviamente verifica solo i numeri superiore, inferiore, e gli spazi. Tuttavia non funziona.

* AGGIORNARE *

Credo che avrei dovuto essere più specifico. Ecco la vera linea di codice reale.

 if [[ "$TITLE" =~ [^a-zA-Z0-9\ ] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; fi 

* AGGIORNARE *

 ./anm.sh: line 265: syntax error in conditional expression ./anm.sh: line 265: syntax error near `&*#]' ./anm.sh: line 265: ` if [[ ! "$TITLE" =~ [a-zA-Z0-9 $%^\&*#] ]]; then RETURN="FAIL" && ERROR="ERROR: Title can only contain upper and lowercase letters, numbers, and spaces!"; return; fi' 

Ci sono un paio di cose importanti da sapere sulla costruzione di [[ ]] di bash. Il primo:

Espansione di parole e espansione del percorso non vengono eseguite sulle parole tra [[ e ]] ; vengono eseguite espansione tilde, espansione di parametri e variabili, espansione aritmetica, sostituzione di comando, sostituzione di processo e rimozione di quote.

La seconda cosa:

Un operatore binario aggiuntivo, ‘= ~’, è disponibile, … la stringa a destra dell’operatore è considerata un’espressione regolare estesa e abbinata di conseguenza … Qualsiasi parte del modello può essere quotata per forzare la corrispondenza come una stringa .

Di conseguenza, $v su entrambi i lati di =~ verrà espanso al valore di tale variabile, ma il risultato non sarà suddiviso in parole o percorso-espanso. In altre parole, è perfettamente sicuro lasciare espansioni variabili non quotate sul lato sinistro, ma è necessario sapere che le espansioni variabili avverranno sul lato destro.

Quindi, se scrivi: [[ $x =~ [$0-9a-zA-Z] ]] , il $0 all’interno della regex sulla destra verrà espanso prima dell’interpretazione della regex, il che probabilmente farà fallire la regex (a meno che l’espansione di $0 con un simbolo di cifra o punteggiatura il cui valore di ascii sia inferiore a una cifra). Se si cita il lato destro come-così [[ $x =~ "[$0-9a-zA-Z]" ]] , allora il lato destro sarà trattato come una stringa ordinaria, non una regex (e $0 sarà ancora espanso). Quello che vuoi veramente in questo caso è [[ $x =~ [\$0-9a-zA-Z] ]]

Allo stesso modo, l’espressione tra [[ e ]] è divisa in parole prima che la regex venga interpretata. Quindi gli spazi nella regex devono essere sfuggiti o quotati. Se vuoi abbinare lettere, cifre o spazi puoi usare: [[ $x =~ [0-9a-zA-Z\ ] ]] . Analogamente, è necessario che gli altri caratteri siano preceduti da caratteri di escape, come # , che avvia un commento se non citato. Certo, puoi inserire il modello in una variabile:

 pat="[0-9a-zA-Z ]" if [[ $x =~ $pat ]]; then ... 

Per le regex che contengono molti caratteri che devono essere salvati o citati per passare attraverso il lexer di bash, molte persone preferiscono questo stile. Ma attenzione: in questo caso, non puoi citare l’espansione della variabile:

 # This doesn't work: if [[ $x =~ "$pat" ]]; then ... 

Infine, penso che quello che stai cercando di fare è verificare che la variabile contenga solo caratteri validi. Il modo più semplice per eseguire questo controllo è assicurarsi che non contenga un carattere non valido. In altre parole, un’espressione come questa:

 valid='0-9a-zA-Z $%&#' # add almost whatever else you want to allow to the list if [[ ! $x =~ [^$valid] ]]; then ... 

! nega il test, trasformandolo in un operatore “non corrisponde” e una class di carattere [^...] regex significa “qualsiasi carattere diverso da ... “.

La combinazione dell’espansione dei parametri e degli operatori di regex può rendere “quasi leggibile” la syntax delle espressioni regolari di bash, ma ci sono ancora alcuni trucchi. (Non ci sono sempre?) Uno è che non si poteva mettere ] in $valid , anche se $valid erano quotati, tranne all’inizio. (Questa è una regola regex di Posix: se vuoi includere ] in una class di caratteri, deve andare all’inizio - può andare all’inizio o alla fine, quindi se hai bisogno di entrambi ] e - , devi iniziare con ] e termina con - , portando alla reisex “So che cosa sto facendo” emoticon: [][-] )

Preferirei usare [:punct:] per quello. Inoltre, a-zA-Z09-9 potrebbe essere solo [:alnum:] :

 [[ $TEST =~ ^[[:alnum:][:blank:][:punct:]]+$ ]] 

Nel caso qualcuno volesse un esempio usando le variabili …

 #!/bin/bash # Only continue for 'develop' or 'release/*' branches BRANCH_REGEX="^(develop$|release//*)" if [[ $BRANCH =~ $BRANCH_REGEX ]]; then echo "BRANCH '$BRANCH' matches BRANCH_REGEX '$BRANCH_REGEX'" else echo "BRANCH '$BRANCH' DOES NOT MATCH BRANCH_REGEX '$BRANCH_REGEX'" fi