Eu suspeito que sed
não é o melhor para isso (e outros podem saber como fazer melhor com sed
), mas aqui vai:
$ sed '2,$ s/.$/&,&/' file | sed -r ':a;N;s/\n(.)(,?.?)(,.)$/\n/;ta' | sed '$d'
A,p,q
B,q,r
C,r,s
Notas
sed '2,$ s/.$/&,&/'
significa duplicar o último caractere em todos exceto na primeira linha, adicionando uma vírgula:
-
2,$
da segunda linha em diante -
s/old/new/
replaceold
comnew
-
.$
o último caractere -
&
o padrão correspondente
sed -r ':a;N;s/\n(.)(,?.?)(,.)$/\n/;ta;'
significa pegar o último caractere de cada linha após o primeiro e colocá-lo no final da linha anterior:
-
-r
use ERE -
:a
label: execute daqui -
;
separa os comandos -
N
leu a próxima linha no espaço de padrão para que possamos usar\n
para representar novas linhas no padrão -
(.)
salve um caractere para mais tarde -
?
zero ou um dos caracteres anteriores -
$
fim da linha -
referência ao padrão salvo
-
ta
se o último comandos
foi bem sucedido, ramifique para:a
e execute o loop novamente -
$d
elimina a última linha
Se o seu arquivo não tiver apenas caracteres únicos entre as vírgulas, você não poderá usar a regex muito simples acima. Aqui está uma versão que funciona se o arquivo for separado por vírgulas. Por exemplo, dado
January,apple
February,pear
March,kiwi
April,mango
Você pode fazer isso, o que também funciona se é apenas um caractere, é claro
$ sed '2,$ s/[^,]*$/&,&/' file | sed -r ':a;N;s/\n([^,]*)(,?[^,]*)(,[^,]*)$/\n/;ta;' | sed '$d'
January,apple,pear
February,pear,kiwi
March,kiwi,mango
sed
scripts podem ser escritos em várias linhas. Não posso afirmar que isso melhora significativamente a legibilidade;) mas pode ser mais portável, pois há restrições quanto ao uso de ;
em versões não-GNU de sed
:
sed '2,$ s/[^,]*$/&,&/' file |
sed -r '{:a
N
s/\n([^,]*)(,?[^,]*)(,[^,]*)$/\n/
ta}' |
sed '$d'
[^,]*
significa zero ou mais caracteres que não são vírgulas.