Ho alcuni file come questo:
abc 123
abc 789
bcd 456
acb 135
Vorrei stampare la prima colonna della riga successiva nella riga corrente.
Uscita desiderata:
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Preferisco usare awk.
Ho alcuni file come questo:
abc 123
abc 789
bcd 456
acb 135
Vorrei stampare la prima colonna della riga successiva nella riga corrente.
Uscita desiderata:
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Preferisco usare awk.
Risposte:
Memorizza la riga precedente:
awk 'NR > 1 { print prev, $1 } { prev = $0 } END { print prev }'
Questo elabora l'input come segue:
prev
, vedere il passaggio successivo) e il primo campo della riga corrente, separati dal separatore del campo di output (il carattere spazio per impostazione predefinita);prev
variabile;awk
Approccio alternativo :
$ awk 'NR == 1{printf "%s", $0;next}{printf " %s\n%s", $1,$0}' input.txt
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
Il modo in cui funziona è semplice: la prima riga è un caso speciale: lo stampiamo senza nuova riga e diciamo a awk di passare alla riga successiva senza eseguire altri blocchi di codice. Successivamente, NR == 1{printf "%s", $0;next}
viene saltato, ma altre parti fanno il lavoro.
Ricorda che fino ad ora abbiamo stampato una stringa formattata senza un nuovo carattere di riga. Pertanto, ciò che viene fatto printf " %s\n%s",$1,$0
ora è la prima parola che viene stampata (e poiché non c'era una nuova riga, rimane sulla stessa riga di output), la nuova riga inserita e quindi l'intera riga stessa (ma non termina con il carattere di nuova riga) . Quindi la prima parola successiva inserita rimarrà sulla stessa riga. Il processo continua fino a quando non raggiungiamo la fine del file.
Il possibile miglioramento è includere il END{print ""}
blocco per inserire la nuova riga finale. In alcuni casi in cui il file risultante deve essere elaborato da altri script potrebbe essere desiderabile.
Mentre l'utente ha richiesto AWK in modo specifico, lo stesso approccio con la stampa di stringhe formattate può essere adottato con altre lingue, ad esempio Python. L'alternativa Python ha fornito a coloro che erano curiosi di sapere come implementarlo in altre lingue:
#!/usr/bin/env python
from __future__ import print_function
import sys
old = None
for index,line in enumerate(sys.stdin):
if index == 0:
print(line.strip(),end=" ")
continue
words = line.strip().split()
print(words[0] + "\n" + line.strip(),end=" ")
E l'utilizzo in questo modo:
$ ./append_first.py < input.txt
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
La stessa idea sulla newline finale si applica qui.
Ecco un brutto sed
modo solo per divertimento
sed '2,$ s/[^ ]\+/& &/; 2,$ s/ /\n/' file | paste -d ' ' - -
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
2,$
dalla seconda riga all'ultimas/[^ ]\+/& &/
raddoppia il primo set di caratteri non bianchi;
separa i comandi, come nella shells/ /\n/
sostituire il primo spazio con una nuova rigapaste -d ' ' - -
incollare questo pasticcio insieme (aggiungi la seconda riga alla terza, la quarta riga alla terza, ecc.)sed
programmi per divertimento, allora forse dovresti provare Code-golf ;-)
Secondo me l'approccio più semplice e più leggibile è:
cut
)tail
)paste
)Esempio: il tuo file inpult di esempio:
abc 123
abc 789
bcd 456
acb 135
Quindi eseguire il comando seguente in un terminale
cut -d' ' -f1 in.txt | tail -n +2 | paste -d' ' file -
Produzione:
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135
La struttura alla base di questa soluzione differisce dalle risposte fornite. Non sono necessarie condizioni, cicli o espressioni regolari.
sed
da solo senzapaste
:sed -r 'N;s/\n(\w+)/\1&/;P;D' somefile.txt