concatena linhas baseadas no primeiro char da próxima linha

5

Eu estou procurando por linhas de contato com base na próxima linha. Até agora, a única maneira que vejo é criar um script de shell que leia linha por linha e faça algo ao longo destas linhas:

while read line
    if $line does not start with "," and $curr_line is empty 
        store line in curr_line
    if $line does not start with "," and $curr_line is not empty
        flush $curr_line to file
        store $line in $curr_line
    if $line starts with "," append to $curr_file, flush to file empty curr_line
done < file

Então estou tentando entender se poderia ser alcançado com sed ou até mesmo grep com redirecionamento. as regras do arquivo são simples. Há no máximo uma e somente uma linha começando com "," que precisa ser anexada à linha anterior.

ex:

line0
line1
line2
,line3
line4
line5
,line6
line7
,line8
line9
line10
line11

O arquivo resultante seria

line0
line1
line2,line3
line4
line5,line6
line7,line8
line9
line10
line11
    
por BitsOfNix 15.11.2016 / 15:47

4 respostas

8

Eu faria:

awk -v ORS= '
  NR>1 && !/,/ {print "\n"}
  {print}
  END {if (NR) print "\n"}' < file

Ou seja, imprime apenas o caractere de nova linha que delimita a linha anterior, se a atual não começar com , .

Em qualquer caso, eu não usaria um while read loop .

    
por 15.11.2016 / 15:55
8

Este é um caso de uso clássico para sed , conforme explicado em Sed One-Liners Explained, Parte I: Espaçamento de Arquivos, Numeração e Conversão de Texto e Substituição , 40. Anexe uma linha à anterior se começar com um sinal de igual "=". (com a modificação óbvia de , para = )

sed -e :a -e '$!N;s/\n,/,/;ta' -e 'P;D' file
line0
line1
line2,line3
line4
line5,line6
line7,line8
line9
line10
line11
    
por 15.11.2016 / 16:03
7

Tudo o que você precisa fazer é sorver o arquivo e remover qualquer nova linha antes das vírgulas:

$ perl -0777pe 's/\n,/,/g' file
line0
line1
line2,line3
line4
line5,line6
line7,line8
line9
line10
line11
    
por 15.11.2016 / 15:55
2

Este é um caso de uso perfeito para ex .

Se você ainda não ouviu falar, ex é o antecessor de vi e, como vi , é especificado pelo POSIX e disponível essencialmente * em qualquer lugar.

ex é realmente projetado para edição de arquivos , mas você pode usá-lo sem salvar as alterações também.

Imprimir alterações, não salve no arquivo:

printf '%s\n' 'g/^,/-j!' %p | ex file.txt

Faça alterações e salve no arquivo:

printf '%s\n' 'g/^,/-j!' x | ex file.txt

Explicação:

Eu uso o comando printf como um wrapper para ex para edições de arquivos com script. Este formulário tem a vantagem de que em qualquer falha (por exemplo, você passa um comando que não é um comando real ou tenta endereçar um número de linha que não existe), o comando simplesmente sai (sem salvar nenhuma alteração) em vez de esperando por outra entrada.

Você pode ver os comandos exatos passados por printf to ex executando o comando printf sozinho:

$ printf '%s\n' 'g/^,/-j!' %p
g/^,/-j!
%p

Ok, o que esses comandos fazem?

Bem, g é o comando "global" e executa o seguinte comando em todas as linhas no "buffer" (arquivo) que corresponde ao regex ^, (início da linha seguido por uma vírgula). / p>

O comando neste caso é -j! . O - é um endereço e significa executar o seguinte comando na linha anterior para a linha atual. (Em outras palavras, nas linhas antes linhas começando com uma vírgula.)

j é para "join" e une a linha com a seguinte linha. O exclam ( ! ) suprime o uso de um caractere de espaço para separar a linha original da linha associada a ela.

% é um endereço que significa "todo o buffer" e p significa "imprimir".

x significa salvar as alterações e sair.

Como eu disse, é um exemplo perfeito de um caso de uso para ex .

* Exceto o Windows. : P

    
por 16.11.2016 / 06:17