GNU/Linux >> Linux Esercitazione >  >> Linux

Verifica della shell se la stringa di più righe contiene il modello specificato nell'ultima riga?

Voglio determinare se una stringa di più righe termina con una riga contenente un modello specificato.

Questi codici non sono riusciti, non corrisponde.

s=`echo hello && echo world && echo OK`
[[ "$s" =~ 'OK$' ]] && echo match

Risposta accettata:

In bash 3.2 o superiori e se la compatibilità con 3.1 non è abilitata (con il compat31 opzione o BASH_COMPAT=3.1 ), citando gli operatori di espressioni regolari (non solo con ma con uno qualsiasi dei bash operatori di virgolette ('...' , "..." , $'...' , $"..." )) rimuove il loro significato speciale.

[[ $var =~ 'OK$' ]]

corrisponde solo nelle stringhe che contengono OK$ letteralmente (che $ corrisponde a un letterale $ )

[[ $var =~ OK$ ]]

corrisponde a stringhe che terminano con OK (quel $ è l'operatore RE che corrisponde alla fine della stringa).

Ciò vale anche per le espressioni regolari memorizzate nelle variabili o il risultato di qualche sostituzione.

[[ $var =~ $regexp ]]   # $var matches $regexp
[[ $var =~ "$string" ]] # $var contains $string

Nota che può diventare imbarazzante perché ci sono alcuni caratteri che devi citare per la sintassi della shell (come spazi vuoti, < , > , & , parentesi quando non corrispondenti). Ad esempio, se vuoi confrontare .{3} <> [)}]& regexp (3 caratteri seguiti da un " <> " , un ) o } e un & ), hai bisogno di qualcosa come:

[[ $var =~ .{3}" <> "[})]& ]]

In caso di dubbio su quali caratteri devono essere citati, puoi sempre utilizzare una variabile temporanea. Ciò significa anche che renderà il codice compatibile con bash31 , zsh o ksh93 :

pattern='.{3} <> [})]&'
[[ $var =~ $pattern ]] # remember *not* to quote $pattern here

Questo è anche l'unico modo (a meno di usare il compat31 opzione (o BASH_COMPAT=3.1 )) puoi utilizzare gli operatori estesi non POSIX delle espressioni regolari del tuo sistema.

Ad esempio, per < per essere trattato come il limite di parole che è in molti motori di espressioni regolari, è necessario:

pattern='<word>'
[[ $var =~ $pattern ]]

Fare:

[[ $var =~ <word> ]]

non funzionerà come bash tratta quelli come operatori di citazione della shell e rimuoverli prima di passare <word> alla libreria regexp.

Nota che è molto peggio in ksh93 dove:

[[ $var =~ "x.*$" ]]

ad esempio corrisponderà su whatever-xa* ma non whatever-xfoo . La citazione sopra rimuove il significato speciale di * , ma non a .$ .

Il zsh il comportamento è più semplice:la citazione non cambia il significato degli operatori regexp lì (come in bash31), il che rende il comportamento più prevedibile (può anche usare le espressioni regolari PCRE invece di ERE (con set -o rematchpcre )).

Correlati:opzione del menu contestuale di Nautilus per creare un nuovo file?

yash non ha un [[...]] costrutto, ma è [ builtin ha un =~ operatore (anche in zsh ). E, naturalmente, [ essendo un comando normale, le virgolette non possono influenzare il modo in cui vengono interpretati gli operatori regexp.

Nota anche che, a rigor di termini, il tuo $s non contiene 3 righe, ma 2 righe complete seguite da una riga non terminata. Contiene hellonworldnOK . Nel OK$ espressione regolare estesa, il $ l'operatore corrisponderebbe solo alla fine della stringa .

In una stringa di 3 righe intere , come hellonworldnOKn (che non saresti in grado di ottenere con la sostituzione dei comandi poiché la sostituzione dei comandi rimuove tutti caratteri di nuova riga finali), il $ corrisponderebbe dopo il n , quindi OK$ non corrisponderebbe.

Con zsh -o pcrematch tuttavia, il $ corrisponde sia alla fine della stringa che prima della nuova riga alla fine della stringa se ce n'è una in quanto non supera il PCRE_DOLLAR_ENDONLY segnala a pcre_compile . Potrebbe essere vista come una cattiva idea poiché generalmente le variabili nelle shell non contengono un carattere di nuova riga finale e, quando lo fanno, generalmente le vogliamo considerate come dati.


Linux
  1. Inserisci più righe di dati in un file dopo le corrispondenze dei modelli utilizzando lo script della shell di Linux

  2. Cat Line X to Line Y su un file enorme?

  3. Mantenere solo la prima riga da ogni sequenza di righe consecutive che corrispondono a uno schema?

  4. Come sapere se una durata è superiore a un'ora su più script di shell?

  5. Come aggiungere più righe a un file?

Come commentare più righe contemporaneamente in Vim Editor

Sostituire le righe che corrispondono a un motivo con le righe di un altro file in ordine?

Come eliminare più righe in Vim

Come scrivere più stringhe di righe usando Bash con variabili?

Inserisci più righe in un file dopo il modello specificato utilizzando lo script della shell

Come posso modificare le righe precedenti in un comando a più righe in Bash?