Bash test: cosa fa "= ~"?


41
#!/bin/bash
INT=-5

if [[ "$INT" =~ ^-?[0-9]+$ ]]; then

echo "INT is an integer."

else

echo "INT is not an integer." >&2

exit 1

fi

Cosa fa il protagonista ~nell'espressione regolare iniziale?



5
Hai letto il manuale di bash? Cosa trovi poco chiaro?
Icaro,

3
Cerca nella pagina man di bash per = ~
Jeff Schaller

Risposte:


46

In ~realtà fa parte dell'operatore =~che esegue una corrispondenza di espressione regolare della stringa alla sua sinistra con l'espressione regolare estesa alla sua destra.

[[ "string" =~ pattern ]]

Si noti che la stringa deve essere quotata e che l'espressione regolare non deve essere quotata.

Un operatore simile viene utilizzato nel linguaggio di programmazione Perl.

Le espressioni regolari comprese bashsono le stesse di quelle che GNU grepcomprende con la -Ebandiera, ovvero l'insieme esteso di espressioni regolari.


Un po 'fuori tema, ma buono a sapersi:

Quando si esegue la corrispondenza con un'espressione regolare contenente gruppi di acquisizione, la parte della stringa acquisita da ciascun gruppo è disponibile BASH_REMATCHnell'array. Lo zeroth / primo ingresso in questo array corrisponde &al pattern di sostituzione di sedcomando 's sostituzione (o $&in Perl), che è il bit della stringa che corrisponde al modello, mentre le voci di indice 1 e poi corrisponde \1, \2ecc in un sedmodello di sostituzione (o $1, $2ecc. in Perl), ovvero i bit corrispondenti a ciascuna parentesi.

Esempio:

string=$( date +%T )

if [[ "$string" =~ ^([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$ ]]; then
  printf 'Got %s, %s and %s\n' \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
fi

Questo può produrre

Got 09, 19 and 14

se l'ora corrente risulta essere 09:19:14.

Il REMATCHbit del BASH_REMATCHnome dell'array deriva da "Corrispondenza espressioni regolari", ovvero "Corrispondenza RE".


In bashshell non simili a Bourne, si può anche usare exprper una corrispondenza limitata delle espressioni regolari (usando solo espressioni regolari di base).

Un piccolo esempio:

$ string="hello 123 world"
$ expr "$string" : ".*[^0-9]\([0-9][0-9]*\)"
123

2
È lo stesso di ciò che grep -Ecomprende solo sui sistemi GNU e solo quando si utilizza una variabile non quotata come modello [[ $var = $pattern ]](vedere [[ 'a b' =~ a\sb ]]vs p='a\sb'; [[ 'a b' =~ $p ]]). Attenzione anche che la quotazione della shell influisce sul significato degli operatori RE e che alcuni caratteri devono essere citati per il tokenizzazione della shell che potrebbe influenzare l'elaborazione RE. [[ '\' =~ [\/] ]]restituisce false. ksh93ha problemi anche peggiori. Vedi zsh(o bash 3.1) per un approccio più sano in cui shell e quotazione RE sono chiaramente separate. Il [built-in zshe yashanche un =~operatore.
Stéphane Chazelas,

2
molto bello off-topic! +1 (
JJoao,

@ StéphaneChazelas Come è "più sano" che entrambi questi match in zsh ?: [[ "This is a fine mess." =~ T.........fin*es* ]]; [[ "This is a fine mess." =~ T.........fin\*es\* ]]. O che anche un citato *corrisponda? [[ "This is a fine mess." =~ "T.........fin*es*" ]].
sorontar

È più sano (IMO) in quanto è regole molto più semplici. La quotazione della shell e l'escape di RE sono chiaramente separate. In [[ a =~ .* ]]o [[ a =~ '.*' ]]o [[ a =~ \.\* ]], la stessa .*RE viene passata =~all'operatore. OTH, in bash, [[ '\' =~ [)] ]]restituisce un errore, lo sapresti senza provare se [[ '\' =~ [\)] ]]corrisponde? Che ne dici [[ '\' =~ [\/] ]](lo fa in ksh93). Che ne dici c='a-z'; [[ a =~ ["$c"] ]](confronta con l' =operatore)? Vedi anche: [[ '\' =~ [^]"."] ]]che restituisce falso ... Nota che si può fare shopt -s compat31in bashper ottenere il zshcomportamento.
Stéphane Chazelas,

zsh/ bash -o compat31'S comportamento per [[ a =~ '.*' ]]è anche coerente con [ a '=~' '.*' ](per [implementazioni che di supporto =~) o expr a : '.*'. OTOH, non è coerente con [[ a = '*' ]]vs [[ a = * ]](ma poi i globs fanno parte del linguaggio shell, mentre le RE non lo sono).
Stéphane Chazelas,

4

Dovresti leggere le pagine man di bash, sotto la [[ expression ]]sezione.

An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3)).

Per farla breve, =~è un operatore, proprio come ==e !=. Non ha nulla a che fare con l'attuale regex nella stringa alla sua destra.


Riesci a capire alcuni esempi che dimostrano l'uso di =~nella vita reale ...?
George Vasiliou,

1
@GeorgeVasiliou Lo uso abbastanza spesso negli script che inseriscono l'output di un comando in una variabile. Quindi la variabile viene controllata per vedere se corrisponde a un modello di stringa. Ciò è utile, ad esempio, se si desidera eseguire alcune azioni in base all'output di un errore da quel comando.
Michael Martinez,

@Sokel Per alcuni, "RTFM" è più facile a dirsi che a farsi. ⋯ man [[ expresssion ]]e man [[non restituire nulla. help [[restituisce informazioni utili — da [[un comando bash interno — ma non dice se =~usa la sintassi regex di base o estesa. ⋯ Il testo che hai citato proviene dalla pagina man di bash . Mi rendo conto che hai detto "leggi le pagine man di bash", ma all'inizio pensavo volessi leggere le pagine man di bash. Ad ogni modo, man bashrestituisce un file enorme, che è lungo 4139 righe (72 pagine). Può essere cercato premendo /▒▒▒, che richiede una regex, il cui sapore - come =~- non è specificato.
Alex Quinn,
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.