Adicionando nova linha após cada enésima ocorrência de delimitador [duplicado]

3

Eu tenho um arquivo roll.txt com os dados abaixo no formato delimitado por vírgulas sem nenhuma nova linha.

'123456789','987651234','129873645','213456789','987612345','543216789','432156789','876543291','213465789','542637819','123456','23456','22234','3456','7890543','34567891,'2345','567'

Eu preciso inserir uma nova linha após cada 6 th ocorrência do delimitador de vírgula sem nenhuma vírgula no final de cada linha.

Abaixo está a saída esperada:

'123456789','987651234','129873645','213456789','987612345','543216789'
'432156789','876543291','213465789','542637819','123456','23456'
'22234','3456','7890543','34567891,'2345','567'

Estou usando o comando abaixo sed que não está funcionando.

sed 's/[^,]//g'
    
por Praveen Verma 28.05.2018 / 00:27

3 respostas

2

com tr e paste :

tr ',' '\n' <infile |paste -sd',,,,,\n'

para maior legibilidade e compreensão:

tr ',' '\n' <infile |paste --serial --delimiters=',,,,,\n'

Nesse caso, quando você quiser adicionar um NewLine a cada palavra, N = 100 posição, talvez não prefira inserir 99 commas ',,,,,,,,,, ... ,\n' ; em vez disso, deixe printf gerá-lo para você com expansão de chaves.

tr ',' '\n' <infile |paste -sd $(printf '%.1s' ,{1..99})'\n'

de man paste :

-d, --delimiters=LIST
       reuse characters from LIST instead of TABs

-s, --serial
       paste one file at a time instead of in parallel
    
por 28.05.2018 / 07:38
1

Pelo menos com GNU sed e supondo que seus campos não podem conter separadores de vírgulas incorporados , você poderia fazer

sed 's/,/\n/6; P; D' roll.txt

que repetidamente tenta substituir a sexta vírgula por uma nova linha, imprime e, em seguida, exclui a parte do espaço padrão até a nova linha.

NOTA: não é necessário implementar um teste / ramificação explícita, pois o comando D implicitamente "reinicia o ciclo" no restante da linha:

D
If pattern space contains no newline, start a normal new cycle as if the d command was issued. Otherwise, delete text in the pattern space up to the first newline, and restart cycle with the resultant pattern space, without reading a new line of input.

(credite a @RakeshSharma por esclarecer isso).

Ex.

sed 's/,/\n/6; P; D' roll.txt 
'123456789','987651234','129873645','213456789','987612345','543216789'
'432156789','876543291','213465789','542637819','123456','23456'
'22234','3456','7890543','34567891,'2345','567'

Como alternativa, com o módulo Text::CSV de Perl:

perl -MText::CSV -ne '
  BEGIN{$p = Text::CSV->new()} 
  @fields = $p->fields() if $p->parse($_); 
  do {
    print join ",", splice @fields, 0, 6; print "\n";
  } while @fields
' roll.txt
'123456789','987651234','129873645','213456789','987612345','543216789'
'432156789','876543291','213465789','542637819','123456','23456'
'22234','3456','7890543','34567891,'2345','567'
    
por 28.05.2018 / 01:05