Con terminale: utilizzo di espressioni regolari II: sostituzioni

In me stesso precedente articolo Ti ho detto a livello di base come funzionano ciascuno dei caratteri speciali più utilizzati delle espressioni regolari. Con queste espressioni regolari è possibile fare ricerche complesse nei file di testo o nell'output di altri comandi. In questo articolo spiegherò come utilizzare il comando sed per trovare e sostituire il testo in un modo molto più potente rispetto alla semplice modifica di un testo con un altro.

Un po 'di più sul comando grep

Prima di iniziare a parlare di sed, vorrei commentare un po 'di più sul comando grep per completare un po' quanto spiegato nell'articolo precedente. Tutto ciò che sto per dire sarà rilevante anche per questo. Più avanti vedremo la relazione tra questo e le ricerche.

Combinazione di espressioni regolari

Molti dei caratteri speciali di cui ho parlato nell'articolo precedente possono essere combinati, non solo con altri caratteri, ma con intere espressioni regolari. Il modo per farlo è usare le parentesi per formare una sottoespressione. Vediamo un esempio di questo. Cominciamo scaricando un testo che possiamo usare per i test. È un elenco di frasi. Per questo useremo il seguente comando:

curl http://artigoo.com/lista-de-frases-comparativas-comicas 2>/dev/null | sed -n 's/.*\(.*\.\)<\/p>/\1/gp' > frases

 Questo ti lascerà nella directory dove avvii un file chiamato «phrases». Puoi aprirlo per dare un'occhiata e ridere. 🙂

Supponiamo ora di voler trovare le frasi che hanno esattamente 6 parole. La difficoltà sta nel formare un'espressione regolare che corrisponda a ciascuna parola. Una parola è una sequenza di lettere, maiuscole o minuscole, che sarebbero qualcosa di simile '[a-zA-Z]+', ma devi anche specificare che queste lettere devono essere separate da caratteri diversi dalle lettere, cioè sarebbe qualcosa di simile '[a-zA-Z]+[^a-zA-Z]+'. Ricorda: il "^" come primo carattere all'interno delle parentesi indica che vogliamo abbinare i caratteri che non sono negli intervalli e il "+" indica 1 o più caratteri.

Abbiamo già un'espressione regolare che può abbinare una parola. Per accoppiarlo con 6, dovrà essere ripetuto 6 volte. Per questo abbiamo usato le chiavi, ma è inutile '[a-zA-Z]+[^a-zA-Z]+{6}', perché il 6 ripeterebbe l'ultima parte dell'espressione regolare e quello che vogliamo è ripetere tutto, quindi quello che devi mettere è questo: '([a-zA-Z]+[^a-zA-Z]+){6}'. Con le parentesi formiamo una sottoespressione e con le parentesi la ripetiamo 6 volte. Ora devi solo aggiungere un "^" davanti e un "$" dietro per abbinare l'intera riga. Il comando è il seguente:

grep -E '^([a-zA-Z]+[^a-zA-Z]+){6}$' frases

E il risultato è proprio quello che volevamo:

È più cantato della Macarena. Sei più finito di Luis Aguilé. Hai meno cultura di una pietra. Conosci più lingue di Cañita Brava. Ha più rughe di Tutan Khamón. Sai meno di Rambo di assistenza all'infanzia.

Si noti che inseriamo il parametro -E perché vogliamo utilizzare espressioni regolari estese per far funzionare il "+". Se usassimo quelli di base, dovremmo sfuggire alle parentesi e alle parentesi graffe.

Riferimenti o riferimenti a ritroso

Se hai installato un correttore ortografico, probabilmente avrai un elenco di parole in formato /usr/share/dict/words. In caso contrario, puoi installarlo in arch con:

sudo pacman -S words

O in Debian con:

sudo aptitude install dictionaries-common

Se vuoi puoi dare un'occhiata al file per vedere quali parole contiene. In realtà è un collegamento al file word della lingua in cui si trova la tua distribuzione. È possibile installare più file di parole contemporaneamente.

Useremo quel file. Si scopre che siamo molto curiosi di conoscere tutti i sette palindromi di lettere là fuori. Per coloro che non lo sanno: un palindromo è una parola capicua, cioè può essere letta da sinistra a destra e da destra a sinistra. Proviamo il seguente comando:

grep '^\(.\)\(.\)\(.\).\3\2\1$' /usr/share/dict/words

Sembra un po 'strano, vero? Se lo proviamo, il risultato dipenderà dalla lingua della tua distribuzione e dalle parole che sono nella tua lista, ma nel mio caso, con la lingua spagnola, il risultato è questo:

anilina anilina laminazione

Vediamo come funziona questa espressione regolare.

A parte il "^" e il "$", di cui sappiamo già a cosa serve, la prima cosa che vediamo a sinistra sono tre gruppi di punti racchiusi tra parentesi. Non lasciarti confondere dalle barre davanti a ogni parentesi. Devono sfuggire alle parentesi perché stiamo usando espressioni regolari di base, ma non hanno altro significato. La cosa importante è che stiamo chiedendo tre caratteri qualsiasi con i punti, ma ciascuno di quei punti è racchiuso tra parentesi. Questo serve per salvare i caratteri che corrispondono a quei punti in modo che possano essere nuovamente referenziati dall'espressione regolare. Questo è un altro uso delle parentesi che tornerà utile in seguito per effettuare le sostituzioni.

Qui è dove vengono i tre numeri sotto con la barra davanti a loro. In questo caso, la barra è importante. Viene utilizzato per indicare che il numero di seguito è un riferimento a ritroso e si riferisce a una delle parentesi precedenti. Ad esempio: \ 1 si riferisce alla prima parentesi, \ 2 alla seconda e così via.

Cioè, con l'espressione regolare che abbiamo inserito, ciò che stiamo cercando sono tutte le parole che iniziano con quattro lettere qualsiasi e quindi hanno una lettera uguale alla terza, un'altra uguale alla seconda e un'altra uguale alla primo. Il risultato sono i palindromi di sette lettere che si trovano nell'elenco delle parole. Proprio come volevamo.

Se usassimo espressioni regolari estese, le parentesi non dovrebbero essere precedute da caratteri di escape, ma con espressioni regolari estese i backreferences non funzionano in tutti i programmi perché non sono standardizzati. Tuttavia, con grep funzionano, quindi potrebbe essere un altro modo per fare lo stesso. Puoi provarlo se vuoi.

Espressioni sostitutive: il comando sed

Oltre alla ricerca, uno degli usi migliori delle espressioni regolari è sostituire testi complessi. Per fare ciò, un modo per farlo è con il comando sed. La potenza del comando sed va ben oltre la sostituzione del testo, ma qui lo userò per questo. La sintassi che userò con questo comando è la seguente:

sed [-r] 's/REGEX/REPL/g' FICHERO

O anche:

COMANDO | sed [-r] 's/REGEX/REPL/g'

Dove REGEX sarà l'espressione regolare di ricerca e REPL quella sostitutiva. Tieni presente che questo comando in realtà non sostituisce nulla nel file che indichiamo, ma quello che fa è mostrarci il risultato della sostituzione nel terminale, quindi non farti spaventare dai comandi che metterò dopo. Nessuno di loro modificherà alcun file sul tuo sistema.

Cominciamo con un semplice esempio. Abbiamo tutti vari file di configurazione nella directory / etc che di solito hanno commenti che iniziano con "#". Supponiamo di voler vedere uno di questi file senza i commenti. Ad esempio, lo farò con fstab. Puoi provare con quello che vuoi.

sed 's/#.*//g' /etc/fstab

Non metterò qui il risultato del comando perché dipende da quello che hai nel tuo fstab, ma se confronti l'output del comando con il contenuto del file vedrai che tutti i commenti sono scomparsi.

In questo comando l'espressione di ricerca è «#.*", Questo è un" # "seguito da un numero qualsiasi di caratteri, ovvero i commenti. E l'espressione di sostituzione, se guardi le due barre di seguito, vedrai che non ce ne sono, quindi quello che sta facendo è sostituire i commenti con niente, cioè eliminarli. Più semplice impossibile.

Adesso faremo l'opposto. Supponiamo che quello che vogliamo è commentare tutte le righe del file. Proviamo in questo modo:

sed 's/^/# /g' /etc/fstab

Vedrai che, nell'output del comando, tutte le righe iniziano con un cancelletto e uno spazio vuoto. Quello che abbiamo fatto è sostituire l'inizio della riga con «# «. Anche questo è un esempio abbastanza semplice in cui il testo da sostituire è sempre lo stesso, ma ora lo complicheremo un po 'di più.

La grazia delle sostituzioni è che nell'espressione di sostituzione puoi usare riferimenti a ritroso come quelli che ti ho detto prima. Torniamo al file della frase che abbiamo scaricato all'inizio dell'articolo. Metteremo tra parentesi tutte le lettere maiuscole che ci sono, ma lo faremo con un comando:

sed 's/\([A-Z]\)/(\1)/g' frases

Quello che abbiamo qui è un riferimento a ritroso nell'espressione di sostituzione che fa riferimento alle parentesi nell'espressione di ricerca. Le parentesi nell'espressione di sostituzione sono parentesi normali. Nell'espressione sostitutiva non hanno alcun significato speciale, sono posti così come sono. Il risultato è che tutte le lettere maiuscole vengono sostituite dalla stessa lettera, qualunque essa sia, racchiusa tra parentesi.

Esiste un altro carattere che può essere utilizzato anche nell'espressione di sostituzione, è "&" ed è sostituito da tutto il testo corrispondente all'espressione di ricerca. Un esempio di ciò potrebbe essere mettere tutte le frasi nel file tra virgolette. Questo può essere ottenuto con questo comando:

sed 's/.*/"&"/g' frases

Il funzionamento di questo comando è molto simile al precedente, solo ora quello che sostituiamo è l'intera riga con la stessa riga racchiusa tra virgolette. Dato che stiamo usando "&", non abbiamo bisogno di mettere le parentesi.

Alcuni comandi utili con espressioni regolari

Ecco alcuni comandi che trovo utili o curiosi e che utilizzano espressioni regolari. Con questi comandi l'utilità delle espressioni regolari è molto migliore rispetto agli esempi che ti ho fornito finora, ma mi è sembrato importante spiegare qualcosa su come funzionano le espressioni regolari per comprenderle.

  • Mostra sezioni di una pagina man:

man bash | grep '^[A-Z][A-Z ]*$'

Ovviamente puoi cambiare il comando bash in quello che vuoi. E poi da uomo, puoi andare direttamente alla sezione che ti interessa usando, ovviamente, un'espressione regolare. Premi «/» per avviare la ricerca e scrivi «^ALIASES$»Per andare alla sezione ALIAS, per esempio. Penso che questo sia il primo utilizzo che ho iniziato a fare delle espressioni regolari alcuni anni fa. Muoversi attraverso alcune pagine del manuale è quasi impossibile senza un trucco come questo.

  • Mostra i nomi di tutti gli utenti della macchina compresi quelli speciali:

sed 's/\([^:]*\).*/\1/' /etc/passwd

  • Mostra i nomi utente, ma solo quelli con shell:

grep -vE '(/false|/nologin)$' /etc/passwd | sed 's/\([^:]*\).*/\1/g'

Può davvero essere fatto con una singola espressione regolare, ma il modo per farlo va oltre ciò che ti ho detto in questi articoli, quindi l'ho fatto combinando due comandi.

  • Inserisci una virgola prima delle ultime tre cifre di tutti i numeri nel file dei numeri:

sed 's/\(^\|[^0-9.]\)\([0-9]\+\)\([0-9]\{3\}\)/\1\2,\3/g' numbers

Funziona solo con numeri fino a 6 cifre, ma può essere chiamato più di una volta per inserire separatori negli altri gruppi di tre cifre.

  •  Estrai tutti gli indirizzi email da un file:

grep -E '\<[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}\>' FICHERO

  • Separare il giorno, il mese e l'anno di tutte le date che compaiono in un file:

sed -r 's/([0-9]{2})[/-]([0-9]{2})[/-]([0-9]{4})/Día: \1, Mes: \2, Año: \3/g' FICHERO

  • Scopri il nostro IP locale:

/sbin/ifconfig | grep 'inet .*broadcast' | sed -r 's/[^0-9]*(([0-9]+\.){3}[0-9]+).*/\1/g'

Questo può essere fatto anche con un singolo comando sed, ma è meglio separarlo in grep e sed per semplicità.

Alcuni indirizzi utili

Ecco alcuni indirizzi che possono essere utili relativi alle espressioni regolari:

  • Libreria di espressioni regolari: Questa è una libreria di espressioni regolari in cui puoi cercare espressioni regolari correlate all'argomento che ti interessa. Per cercare indirizzi web, ID o altro.
  • RegExr: Un controllo di espressioni regolari in linea. Ti consente di inserire un testo e applicare un'espressione regolare ad esso, cercare o sostituire. Fornisce informazioni sull'espressione regolare e sono disponibili alcune opzioni per modificarne il comportamento.
  • Tester di espressioni regolari: È un addon per Firefox che consente di controllare le espressioni regolari dal browser.

Conclusione

Per ora è tutto. Le espressioni regolari sono complesse ma utili. Ci vuole tempo per impararli, ma se sei come me, giocare con loro sembrerà divertente e, a poco a poco, li padroneggerai. È un mondo intero. Ci sarebbe ancora molto da dire, su quantificatori pigri, regex in stile PERL, multiline, ecc. E poi ogni programma ha le sue caratteristiche e le sue varianti, quindi il miglior consiglio che posso darti è quello di guardare sempre la documentazione del programma che stai usando ogni volta che devi scrivere un'espressione regolare in un nuovo programma.

Hey! …HEY! … SVEGLIATI! … COSA FATE TUTTI DORMENDO? 🙂

Fonti

Alcune delle idee e degli esempi per le espressioni regolari in questo articolo ho preso da qui:


Lascia un tuo commento

L'indirizzo email non verrà pubblicato. I campi obbligatori sono contrassegnati con *

*

*

  1. Responsabile dei dati: Miguel Ángel Gatón
  2. Scopo dei dati: controllo SPAM, gestione commenti.
  3. Legittimazione: il tuo consenso
  4. Comunicazione dei dati: I dati non saranno oggetto di comunicazione a terzi se non per obbligo di legge.
  5. Archiviazione dati: database ospitato da Occentus Networks (UE)
  6. Diritti: in qualsiasi momento puoi limitare, recuperare ed eliminare le tue informazioni.

  1.   vivace suddetto

    Magistrale!!!

    1.    hexborg suddetto

      Non è così male, ma grazie mille. Spero che alle persone piaccia. 🙂

      1.    oscar suddetto

        Mi piace ah!

        1.    hexborg suddetto

          Allora devo aver fatto qualcosa di giusto. LOL !! 🙂

          Grazie mille per il tuo commento.

          1.    Blaire pascal suddetto

            Cazzo continua a scrivere amico, continua così.

          2.    hexborg suddetto

            @ Blaire Pascal: commenti come i tuoi lo incoraggiano. 🙂 Grazie mille !!

      2.    Città suddetto

        Anche a me è piaciuto ... grazie 🙂

        1.    hexborg suddetto

          Grazie per il commento. Spero di scriverne altri. 🙂

  2.   Mariano suddetto

    I tuoi post sono fantastici, impari molto, anzi impari a svolgere compiti in modo elegante ed efficiente.

    Hai pensato di raccogliere tutti i tuoi post di script di shell? Ordinato in un pdf sarebbe un ottimo manuale.

    Coraggio e grazie mille!

    1.    hexborg suddetto

      Grazie mille!! Non è una cattiva idea. Al momento sono solo due, ma ci penserò più tardi. 🙂

  3.   Kiev suddetto

    ottimo articolo, 5+.

    1.    hexborg suddetto

      Grazie. Sono felice che ti piaccia. 🙂

  4.   sebastian suddetto

    Eccellente! Devo cambiare la seguente espressione e non so come farlo:
    192.168.0.138/Server di 192.168.0.111/data
    Il problema sta nel simbolo "/".
    Sto usando il comando:
    trova. -name "* .txt" -exec sed -i 's / TEXT1 / TEXT2 / g' {} \;
    Cosa viene utilizzato per eseguire questo tipo di attività in modo non corretto, ma non posso ...
    Qualcuno sa come dovrei farlo?
    Abbraccio!
    Sheba

    1.    hexborg suddetto

      Quello che devi fare è sfuggire al personaggio in questo modo:

      trova. -name "* .txt" -exec sed -i 's / \ / Server / \ / data / g' {} \;

      Puoi anche usare un altro separatore in sed. Non deve essere un bar. Sed consente di utilizzare qualsiasi carattere. Ad esempio, questo sarebbe più chiaro:

      trova. -name "* .txt" -exec sed -i 's | / Server | / data | g' {} \;

      E se hai intenzione di copiare e incollare i comandi da questo commento, fai attenzione alle virgolette, che wordpress li cambia per quelli tipografici. 🙂

      Saluti.

  5.   sebastian suddetto

    Eccellente!!!!
    Sto cercando questa soluzione da molto tempo.
    Qui lascio il comando completo che ho usato

    trova. -name "* .txt" -exec sed -i 's | 192 \ .168 \ .0 \ .238 \ / Server | 192 \ .168 \ .0 \ .111 \ / data | g' {} \;

    Il vantaggio di questo comando è che cambia tutti i file .txt (o l'estensione che desideri) in modo ricorsivo ... Devi stare molto attento!
    Ma è molto utile !!!

    Bene, grazie di tutto e mille complimenti a tutto il gruppo.
    Li leggo sempre dalla posta!
    Abbracci
    Sheba