bash / sed / awk / etc remove todas as outras novas linhas

39

Um comando bash gera isso:

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

Eu gostaria de canalizá-lo para algo para torná-lo assim:

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
[...]

ou seja, remova qualquer outra linha nova

Eu tentei, ... |tr "\nGroup" " "mas ele removeu todas as novas linhas e comeu algumas outras cartas também. obrigado

carrilhão
fonte
2
tré inteiramente baseado em caracteres: você pediu a tr para remover novas linhas e todos os 'G', 'r', 'o', 'u' e 'p'.
precisa

Respostas:

80

não pode testar agora, mas

... | paste - - 

deveria fazê-lo

Glenn Jackman
fonte
5
+1 - funciona e é elegante. (Ele coloca um separador entre as linhas - paste -d ' ' - -irá adicionar um espaço em vez se necessário)
cyberx86
4
Você poderia explicar como o comando funciona? Por que existem dois -? Graças
bbaja42
7
pasteé utilizado para concatenar as linhas correspondentes de ficheiros: paste file1 file2 file3 .... Se um dos argumentos "arquivo" for "-", as linhas serão lidas a partir da entrada padrão. Se houver 2 argumentos "-", colar terá 2 linhas de stdin. E assim por diante. Veja a página do manual .
Glenn Jackman
10

Uma possibilidade é:

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

Se o número da linha for divisível por 2, termine com uma nova linha, caso contrário, termine com um espaço.

(Testado em: CentOS 6, GNU Awk 3.1.7)

Usando sed (veja explicação ):

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

Leitura adicional:

cyberx86
fonte
8

Se você deseja usar sed, não há razão para ler o arquivo inteiro na memória. Você pode mesclar todas as outras linhas como esta:

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

Use qualquer caractere que desejar em vez do espaço.

Aqui está outra maneira de usar o awk:

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

Ele if/elselida com o caso em que há um número ímpar de linhas no arquivo. Sem ele, a última linha ímpar é impressa duas vezes. Caso contrário, para comparação, você pode fazer:

awk '{printf "%s", $0; getline; print " " $0}'
Pausado até novo aviso.
fonte
1
Um comentário tardio: 1) sempre use um especificador de formato para printf, caso a string tenha sinais de porcentagem, 2) para evitar a última linha duplicada, defina $ 0 como "" -awk '{printf "%s", $0; $0=""; getline; print " " $0}'
glenn jackman 10/12/12
3

A maneira mais idiomática de fazer isso awké a seguinte:

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

Emite:

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

Para explicá-lo, precisamos definir cada uma das variáveis ​​internas:

  • RSseparador de registros. O padrão é \n(nova linha).
  • ORSseparador de registros de saída. O padrão é \n(nova linha).
  • FSseparador de campo. O padrão é (espaço).
  • NR número de registro.

Como o separador de registros padrão é a nova linha, um registro é, como padrão, uma linha.

NR%2é o módulo de NR/2, de modo que será ou 0ou 1. 0para linhas 1pares e linhas ímpares.

var=condition?condition_if_true:condition_if_false é o operador ternário.

Todos juntos, dizendo ORS=NR%2?FS:RSque estamos definindo o separador de registros de saída:

  • se o número de registros estiver no formulário 2k + 1, ou seja, em linhas pares, os separadores de registros de saída serão configurados para FS, ou seja, um espaço.
  • se o número de registros estiver no formulário 2k, ou seja, em linhas ímpares, os separadores de registros de saída serão configurados para RS, ou seja, uma nova linha.

Dessa forma, as linhas ímpares terminam com um espaço, que é então unido à próxima linha. Após essa linha, uma nova linha é impressa.

Mais informações no Idiomatic awk .

fedorqui
fonte
2

Isso funciona para mim no Linux:

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

Isso substitui um espaço vazio por um caractere de nova linha; você deve escapar do caractere de nova linha para que as coisas funcionem corretamente.

Bret McMillan
fonte
Isso remove todas as novas linhas, não todas as outras linhas.
Trenton
2

Na festança:

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

Se Perl é uma opção:

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

s/\n/ /substitui nova linha por espaço
$.é o número da linha

Chris Koknat
fonte
-1

Que tal usar grep?

.. | grep -v '^Group State'
pkhamre
fonte
Isso elimina as linhas alternativas. O OP quer que eles sejam anexados.
Pausado até novo aviso.
Sim, depois de reler a pergunta que eu só percebi que :)
pkhamre