2014-05-10 10 views
5

Ho un file di testo come questo:Come sostituire tutte le partite con un numero incrementale in BASH?

AAAAAA this is some content. 
This is AAAAAA some more content AAAAAA. AAAAAA 
This is yet AAAAAA some more [AAAAAA] content. 

ho bisogno di sostituire tutte le occorrenze di AAAAAA con un numero incrementato, ad esempio, l'uscita sarebbe simile a questa:

1 this is some content. 
This is 2 some more content 3. 4 
This is yet 5 some more [6] content. 

Come posso sostituire tutte le partite con un numero incrementale?

+1

Qualcuno ha chiesto lo stesso problema nel tag rubino ieri. Mi chiedo solo se voi ragazzi siete nella stessa classe. – devnull

risposta

8

Ecco un modo per farlo:

$ awk '{for(x=1;x<=NF;x++)if($x~/AAAAAA/){sub(/AAAAAA/,++i)}}1' file 
1 this is some content. 
This is 2 some more content 3. 4 
This is yet 5 some more [6] content. 
+1

Non farei quello secondo - considera cosa farebbe se una riga di input contenesse 'Un set di ripetizioni AAAAAA'. –

+2

Grazie a @EdMorton. È vero, la domanda originale immagino sia stata successivamente modificata per mostrare solo un set di 6 A. Ho rimosso il secondo suggerimento. –

1

Una soluzione perl:

perl -pe 'BEGIN{$A=1;} s/AAAAAA/$A++/ge' test.dat 
+0

Interessante (per me comunque!) Differenza semantica tra awk e perl qui - in perl 'A' viene incrementata una volta per sostituzione ma in awk (' awk -vRS = '^ $' 'BEGIN {A = 1} gsub (/ AAAAAA /, A ++) '') A viene incrementato solo una volta, dopo le sostituzioni. –

+2

@EdMorton: Perl può oscillare in entrambe le direzioni. La bandiera "e" significa "valutare la sostituzione ogni volta". Se avessi scritto 's/AAAAAA/{$ A ++}/g', avrei ottenuto un risultato diverso. (In Python, puoi scrivere 're.sub ("A {6}", string, callable) 'ma se vuoi che il callable faccia qualcosa di interessante, probabilmente devi definirlo; non è una comoda interfaccia per one-liner. Lua sarebbe stata un'altra possibilità: consente anche la sostituzione di callables e ha una sintassi più comoda, ma purtroppo non è installata di default sulla maggior parte delle distro. – rici

+0

Ah perl, dove anche il codice che pensi sia chiaro risulta avere una svolta :-). L'awk più vicino equivalente alla dichiarazione originale allora sarebbe 'awk -vRS = '^ $' '{while (sub (/ AAAAAA /, ++ A));} 1' file'. Grazie per la spiegazione. –

0

Forse qualcosa di simile

#!/bin/bash 
NR=1 
cat filename while read line 
do 
    line=$(echo $line | sed 's/AAAAA/$NR/') 
    echo ${line} 
    NR=$((NR + 1)) 
done 
+1

Sostituisce solo un'istanza del motivo per riga e incrementa il contatore anche per le linee che non presentano istanze del motivo. E non si espande '$ NR' nella sostituzione perché si usa il preventivo singolo invece del doppio preventivo – rici

3

Questo potrebbe funzionare per voi (GNU SED) :

sed -r ':a;/AAAAAA/{x;:b;s/9(_*)$/_\1/;tb;s/^(_*)$/0\1/;s/$/:/;s/([^_])(_*):.*\1(.).*/\3\2/;s/_/0/g;x;G;s/AAAAAA(.*)\n(.*)/\2\1/;ta}' file 

Questo è un esempio di giocattolo, perl o awk sarebbe la soluzione migliore per una soluzione.

La soluzione agisce solo sulle righe che contengono la stringa richiesta (AAAAAA).

Il buffer di mantenimento viene utilizzato come posizione per mantenere il numero intero incrementato.

In visione: quando si incontra una stringa richiesto, il numero intero nello spazio stiva viene incrementato, allegata alla riga corrente, scambiato per la stringa richiesta e il processo viene ripetuto fino a quando tutte le occorrenze della stringa sono contabilizzati.

L'incremento di un intero scambia semplicemente l'ultima cifra (diversa da quella finale di 9) per il numero intero successivo in sequenza, ovvero da 0 a 1, da 1 a 2 ... da 8 a 9. Quando si verificano 9 finali, ogni 9 finale viene sostituito da un carattere non intero es. '_'. Se il numero che si incrementa consiste interamente di 9 finali, a fronte del numero viene aggiunto 0 in modo che possa essere incrementato a 1. Dopo l'operazione di incremento, gli ultimi 9 (ora _) vengono sostituiti da "0".

Come esempio dire il numero intero 9 deve essere incrementato:

9 è sostituito da _, un 0 viene anteposta (0_), il 0 viene scambiato per 1 (1_), il _ è sostituito dal 0 . risultante nel numero 10.

Vedere commenti diretti a @jaypal per ulteriori note.

+0

Ma mi piacciono i giocattoli :-) –

+0

Ogni volta che ne hai la possibilità, puoi aggiornare la risposta per aggiungere qualche spiegazione. Mi piacerebbe davvero imparare il processo di creazione di una tabella di ricerca per referenziare i dati. (Sto indovinando che la sequenza numerica è per quello). –

+1

@jaypal una spiegazione delle tabelle di ricerca in sed può essere trovato [qui] (http://sed.sf.net/grabbag/tutorials/lookup_tables.txt). Incremento di un numero [qui] (http://sed.sourceforge.net/grabbag/scripts/incr_num.sed). – potong