bash / sed / awk / etc rimuove ogni altra riga


39

un comando bash genera questo:

Runtime Name: vmhba2:C0:T3:L14
Group State: active
Runtime Name: vmhba3:C0:T0:L14
Group State: active unoptimized
Runtime Name: vmhba2:C0:T1:L14
Group State: active unoptimized
Runtime Name: vmhba3:C0:T3:L14
Group State: active
Runtime Name: vmhba2:C0:T2:L14
Group State: active

Vorrei collegarlo a qualcosa per farlo apparire così:

Runtime Name: vmhba2:C0:T1:L14 Group State: active 
Runtime Name: vmhba3:C0:T3:L14 Group State: active unoptimized
Runtime Name: vmhba2:C0:T2:L14 Group State: active
[...]

cioè rimuovere ogni altra newline

Ho provato ... |tr "\nGroup" " "ma ha rimosso tutte le nuove righe e ho mangiato anche altre lettere. Grazie


2
trè interamente basato sui caratteri: hai chiesto a tr di rimuovere le nuove righe e tutte le "G", "r", "o", "u" e "p".
Glenn Jackman,

Risposte:


80

non posso testare adesso, ma

... | paste - - 

dovrebbe farlo


5
+1: funziona ed è elegante. (Mette una scheda tra le linee - paste -d ' ' - -aggiungerà invece uno spazio se necessario)
cyberx86

4
Potresti spiegare come funziona il comando? Perché ce ne sono due -? Grazie
bbaja42

7
pasteviene utilizzato per concatenare linee corrispondenti da file: paste file1 file2 file3 .... Se uno degli argomenti "file" è "-", le righe vengono lette dall'input standard. Se ci sono 2 "-" argomenti, quindi incolla prende 2 righe da stdin. E così via. Vedi la pagina man .
Glenn Jackman,

10

Una possibilità è:

awk 'ORS=NR%2?" ":"\n"'

Se il numero di riga è divisibile uniformemente per 2, termina con una nuova riga, altrimenti termina con uno spazio.

(Testato su: CentOS 6, GNU Awk 3.1.7)

Usando sed (vedi spiegazione ):

sed ':a;N;$!ba;s/\nGroup/ Group/g'

Ulteriori letture:


8

Se si desidera utilizzare sed, non c'è motivo di leggere l'intero file in memoria. Puoi unire ogni altra riga in questo modo:

sed 'N;s/\n/ /' inputfile

Usa qualsiasi personaggio che desideri al posto dello spazio.

Ecco un altro modo di usare awk:

awk '{printf "%s", $0; if (getline) print " " $0; else printf "\n"}' inputfile

I if/elsegestisce il caso in cui v'è un numero dispari di righe nel file. Senza di essa, l'ultima riga dispari viene stampata due volte. Altrimenti, per il confronto, potresti fare:

awk '{printf "%s", $0; getline; print " " $0}'

1
Un commento in ritardo: 1) usa sempre un identificatore di formato per printf nel caso in cui la stringa abbia segni di percentuale, 2) per evitare l'ultima riga duplicata, imposta $ 0 su "" -awk '{printf "%s", $0; $0=""; getline; print " " $0}'
glenn jackman,

3

Il modo più idiomatico per farlo awkè il seguente:

awk 'ORS=NR%2?FS:RS' file

Emette:

Runtime Name: vmhba2:C0:T3:L14 Group State: active
Runtime Name: vmhba3:C0:T0:L14 Group State: active unoptimized
Runtime Name: vmhba2:C0:T1:L14 Group State: active unoptimized
Runtime Name: vmhba3:C0:T3:L14 Group State: active
Runtime Name: vmhba2:C0:T2:L14 Group State: active

Per spiegarlo, dobbiamo definire ciascuna delle variabili incorporate:

  • RSseparatore di record. L'impostazione predefinita è \n(nuova riga).
  • ORSseparatore record di uscita. L'impostazione predefinita è \n(nuova riga).
  • FSseparatore di campo. Il valore predefinito è (spazio).
  • NR numero di record.

Poiché il separatore di record predefinito è la nuova riga, un record è, come impostazione predefinita, una riga.

NR%2è il modulo di NR/2, in modo che sia o 0o 1. 0per linee pari e 1per linee dispari.

var=condition?condition_if_true:condition_if_false è l'operatore ternario.

Tutti insieme, dicendo ORS=NR%2?FS:RSche stiamo definendo il separatore del record di output:

  • se il numero di record è nel modulo 2k + 1, ovvero su linee pari, i separatori del record di output sono impostati su FSuno spazio.
  • se il numero di record si trova sul modulo 2k, ovvero su righe dispari, i separatori di record di output vengono impostati su RSuna nuova riga.

In questo modo, le linee dispari terminano con uno spazio, che viene quindi unito alla linea successiva. Dopo quella linea, viene stampata una nuova linea.

Maggiori informazioni in Idiomatic awk .


2

Questo funziona per me su Linux:

... | tr "\\n" " "

Questo sostituisce uno spazio vuoto per un carattere di nuova riga; si deve sfuggire al carattere di nuova riga le cose funzionino correttamente.


Ciò rimuove ogni newline, non ogni altra newline.
Trenton,

2

In bash:

... | while read l1; do read l2; echo "$l1 $l2"; done

1

Se Perl è un'opzione:

perl -pe 's/\n/ / if $. % 2 == 1' file

s/\n/ /sostituisce newline con spazio
$.è il numero di riga


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.