Combine várias linhas dinamicamente no unix

3

Eu tenho o cenário abaixo:

Iteração 1 -

Ddd
Bbb
Ccc
Ddd
Eee
Fff
Ddd

Iteração 2 -

Ddd
Bbb
Ddd

Eu quero combinar os dados conforme abaixo -

Saída da iteração 1 -

Ddd Bbb Ccc
Ddd Eee Fff
Ddd

Saída da iteração 2 -

Ddd bbb
Ddd

Eu quero usar o awk NR para criar blocos dinâmicos para combinar dados, ou seja, NR% 3 na Iteração 1 Saída e NR% 2 na Iteração 2 Saída.

Eu tentei usar a variável para atribuir dinamicamente os valores, ou seja, NR% $ cnt, mas resultou em erro.

Por favor, ajude.

    
por Tarun Mathur 27.07.2018 / 19:42

3 respostas

2

Meu método não exige nenhuma suposição sobre com que frequência Ddd ocorre; pode ocorrer de forma irregular. O método deve funcionar, a menos que exista um caractere nulo em algum lugar na entrada ou a entrada não termine com uma nova linha (consulte this ), ou suas ferramentas são limitadas (por exemplo, sed -z não é especificado por POSIX).

sed '1! s/^Ddd$/\x00Ddd/' | tr '\n' ' ' | sed -z 's/ $/\n/' | tr -d '
sed '1! s/^Ddd$/\x00Ddd/' | tr '\n' ' ' | sed -z 's/ $/\n/' | tr -d '%pre%'
'

O procedimento:

  1. sed detecta linhas que são Ddd e precede cada uma com um caractere nulo, a menos que a linha seja a primeira. Esses caracteres nulos agora separam nossas futuras linhas.
  2. tr substitui cada caractere de nova linha por um caractere de espaço. Isso constrói nossas futuras linhas: as linhas antigas agora são separadas por espaços.
  3. Cada uma, mas a última linha a ser, contém um espaço extra no final da linha inicial originalmente anterior a Ddd ; a última linha a ser contém um espaço extra da nova linha final requerida pelo POSIX. sed -z lê sequências com terminação nula (linhas a serem) e substitui esses caracteres de espaço à direita por novas linhas normais. Neste momento as futuras linhas se tornam linhas regulares.
  4. tr -d remove caracteres nulos.
por 27.07.2018 / 21:21
1

Você pode usar isso (é do GNU coreutils):

pr --columns=3 --across --separator=' ' --omit-pagination    # pr -3 -a -s' ' -T

Ele vai ler stdin ou de um arquivo. Dando a sua primeira coluna de dados, a saída é a seguinte:

Ddd Bbb Ccc
Ddd Eee Fff
Ddd

Altere --columns=3 para --columns=2 para o segundo arquivo:

Ddd bbb
Ddd
    
por 27.07.2018 / 20:00
1

Aqui está uma opção (é do GNU findutils):

xargs --no-run-if-empty --max-args=3    # xargs -r -n3

Ele vai ler stdin ou de um arquivo. Dando a sua primeira coluna de dados, a saída é a seguinte:

Ddd Bbb Ccc
Ddd Eee Fff
Ddd

Altere --max-args=3 para --max-args=2 para o segundo arquivo:

Ddd bbb
Ddd

Aqui está outra opção, desta vez baseada em torno de awk . Altere NR % 3 para NR % 2 para o segundo arquivo.

awk '{ printf "%s", $0 } { if (NR % 3) { printf " " } else { printf "\n" } }'
    
por 27.07.2018 / 23:42

Tags