2012-05-18 19 views
9

Voglio sostituire tutte le coppie di parentesi quadre in un file, ad esempio, [some text], con \macro{some text}, ad esempio:Come sostituire parentesi quadre abbinate con altre sintassi con sed?

This is some [text]. 
This [line] has [some more] text. 

questo diventa:

This is some \macro{text}. 
This \macro{line} has \macro{some more} text. 
  • Le coppie si verificano solo sulle singole linee , mai attraverso più linee.
  • A volte potrebbe esserci più di una coppia su una singola riga, ma non vengono mai annidati.
  • Se una parentesi si trova da sola su una linea, senza una coppia, non dovrebbe essere modificata.

Come posso sostituire queste coppie di parentesi con questo codice?

risposta

6
sed -e 's/\[\([^]]*\)\]/\\macro{\1}/g' file.txt 

Questo cerca una parentesi aperta, un numero qualsiasi di parentesi esplicitamente non di chiusura, quindi una parentesi chiusa. Il gruppo viene catturato dai paren e inserito nell'espressione sostitutiva.

2

La seguente espressione corrisponde al modello [a-z, A-Z and space] e lo sostituisce con \macro{<whatever was between the []>}

sed -e 's/\[\([a-zA-Z ]*\)\]/\\macro{\1}/g' 

Nell'espressione forma \(... \) un gruppo match che è possibile fare riferimento più avanti nella sostituzione come \1

+0

Questo potrebbe essere corretto per i dati di test forniti ma '[^]] *' è una soluzione migliore. – potong

3

uso gruppi

sed 's|\[\([^]]*\)\]|\\macro{\1}|g' file 
21

C'è voluto un po facendo, ma ecco:

sed -i.bkup 's/\[\([^]]*\)\]/\\macro{\1}/g' test.txt 

Vediamo se riesco a spiegare questa espressione regolare:

  1. Il \[ sta abbinando una parentesi quadra. Poiché [ è un carattere di espressione regolare magico valido, il backslash significa che corrisponde al carattere letterale.
  2. Il (...) è un gruppo di acquisizione. Cattura la parte dell'espressione regolare che voglio. Posso avere molti gruppi di cattura, e in sed li posso riferire come \1, \2, ecc
  3. All'interno del gruppo di cattura \(...\). Ho [^]]*.
    1. La sintassi [^...] indica qualsiasi carattere ma.
    2. [^]] indica qualsiasi carattere tranne una parentesi di chiusura.
    3. * significa zero o più dei precedenti. Ciò significa che sto catturando zero o più caratteri che non stanno chiudendo le parentesi quadre.
  4. Il \] significa la chiusura di parentesi quadra

Diamo un'occhiata alla linea questo è [alcune] più [Testo]

  • In # 1 di cui sopra, mi cattura il primo parentesi quadra aperta davanti alla parola qualche. Tuttavia, non è in un gruppo di acquisizione. Questo è il primo personaggio che ho intenzione di sostituire.
  • Ora avvio un gruppo di acquisizione. Sto catturando secondo 3.2 e 3.3 sopra, iniziando con la lettera s in alcuni quanti caratteri possibili che non stanno chiudendo le parentesi quadre. Ciò significa che sto facendo corrispondere [some, ma solo catturando some.
  • Al n. 4, ho terminato il mio gruppo di acquisizione. Ho abbinato per scopi di sostituzione [some e ora sto corrispondendo sull'ultima parentesi quadra di chiusura. Ciò significa che sto corrispondendo allo [some]. Nota che le espressioni regolari sono normalmente golose. Spiegherò di seguito perché questo è importante.
  • Ora, posso abbinare la stringa di sostituzione. Questo è molto più facile. È \\macro(\1). Il \1 viene sostituito dal mio gruppo di acquisizione. Il \\ è solo un backslash. Quindi, sostituirò [some] con \macro{some}.

Sarebbe molto più semplice se potessi avere un singolo set di parentesi quadre in ogni riga. Quindi avrei potuto farlo:

sed -i.bkup 's/\[\(.*\)\]/\\macro(\1)/g' 

Il gruppo di acquisizione ora sta dicendo qualcosa tra parentesi quadre. Tuttavia, il problema è che le espressioni regolari sono avide, il che significa che avrei dovuto corrispondere dallo s allo some fino allo t finale nel testo. La 'x' qui sotto mostra il gruppo di cattura. Il [ e ] mostrano le parentesi quadre che sto corrispondenti a:

this is [some] more [text] 
     [xxxxxxxxxxxxxxxx] 

Questo è diventato più complesso, perché ho dovuto corrispondere su personaggi che hanno avuto un significato speciale per le espressioni regolari, così vediamo un sacco di backslashing. Inoltre, ho dovuto tenere conto della golosità delle espressioni regolari, che ha ottenuto la bella stringa non corrispondente [^]]* per abbinare qualsiasi cosa non fosse una parentesi chiusa. Aggiungi le parentesi quadre prima e dopo \[[^]]*\] e non dimenticare il gruppo di acquisizione \(...\): \[\([^]]*\)\] E ottieni un grande casino di un'espressione regolare.

+0

Ottima spiegazione! Comunque la sostituzione dovrebbe essere circondata da '\ macro {...}' – potong

+0

Correzione minore ... Modificata la mia risposta. Su un piccolo schermo, a volte è difficile vedere la differenza tra '(' e '{'. –

Problemi correlati