Como posso substituir todos os pontos e vírgulas após o primeiro?

4

Esse problema está relacionado à minha tentativa de importar perguntas e suas respostas em um arquivo do Excel para o arquivo .txt, que o programa de flashcards da Anki manipula conforme descrito aqui . Eu não posso ter mais de dois campos, então eu preciso fazer opções em um campo.

Dados armazenados como CSV do LibreOffice (ponto-e-vírgula como separador de campo - única distinção que o manual diz) conforme instruído no manual da Anki

Question ipsun; option 1 ; option 2 ; option 3 ; option 4 ; ... ; option n
Question ipsun; option 1 ; option 2 ; option 3 ; option 4 ; ... ; option n
...

em que cada entrada com todas as opções está em uma linha, ou seja, um "cartão de memória". Em um cartão, parte frontal antes do ponto e vírgula, e parte traseira após o ponto e vírgula. Segundo flashcard na nova linha e assim por diante.

Saída desejada que deve estar em UTF-8

Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
...

Meu pseudocódigo em Perl é baseado nessa resposta

perl -00 -pe s/;/
perl -00 -pe '   # each record is separated by blank lines (-00)
                 # read the file a record at a time and auto-print (-p)
    s/;/
Question ipsun; option 1 ; option 2 ; option 3 ; option 4 ; ... ; option n
Question ipsun; option 1 ; option 2 ; option 3 ; option 4 ; ... ; option n
...
/; # turn the first semicolon into a null byte s/;/ |/g; # replace all other semicolons with " |" s/
Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
...
/;/ # restore the first semicolon ' file
/; s/;/ |/g; s/
perl -00 -pe s/;/
perl -00 -pe '   # each record is separated by blank lines (-00)
                 # read the file a record at a time and auto-print (-p)
    s/;/%pre%/;    # turn the first semicolon into a null byte
    s/;/ |/g;     # replace all other semicolons with " |"
    s/%pre%/;/     # restore the first semicolon
' file
/; s/;/ |/g; s/%pre%/;/' file
/;/' file

Comentou

%pre%

Como você pode substituir todos os pontos e vírgulas após o primeiro ponto e vírgula?

    
por Léo Léopold Hertz 준영 11.06.2015 / 14:39

5 respostas

7
sed 'y/|;/\n|/;s/|/;/;y/\n/|/' <<\IN
Question ipsun; option 1 ; option 2 ; option 3 ; option 4 ; ... ; option n
IN

Note que isso não não usa um regexp para lidar com a maioria das substituições, mas usa uma tradução mais básica (e com muito mais desempenho) função para o fazer - e fá-lo de uma forma portátil POSIX. Isso deve funcionar em qualquer máquina com um POSIX sed instalado.

Ele traduz ; ponto e vírgula para | pipes e | pipes para \n ewlines simultaneamente. Os | pipes são separados como \n ewlines, caso algum deles ocorra em uma linha de entrada. Em seguida, ele s/// ubstituta o primeiro | pipe ocorrendo por ; ponto e vírgula, em seguida, converte todos \n ewlines em | pipes - restaurando assim qualquer um que possa ter reservado para manipular de forma robusta o único s/// ubstitution.

Enquanto eu uso um documento <<\IN here por causa da demonstração de copiar / pastável, você provavelmente deve usar <infile >outfile .

OUTPUT:

Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
    
por 11.06.2015 / 19:14
9

Com o GNU sed :

sed 's/;/|/2g'

Que globalmente substitui ; por | a partir da segunda ocorrência.

Embora sed 's/;/|/2 e s/;/|/g sejam POSIX, a combinação não é e o comportamento varia entre as implementações. Com a implementação GNU de sed , no entanto, o comportamento está claramente documentado.

    
por 11.06.2015 / 20:56
4

Basta que sed -e 's/;/|/g' -e 's/|/;/' data.csv receba você:

Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n

Que parece com o que você queria.

    
por 11.06.2015 / 19:41
2

Eu não notei uma versão awk , então aqui está:

awk -F';' '{for(i=2;i<=NF;i++)gsub(" ; "," | ");print}' testfile1.txt

Exemplo de saída:

$ cat testfile1.txt                                                                                
Question ipsun; option 1 ; option 2 ; option 3 ; option 4 ; ... ; option n
Question ipsun; option 1 ; option 2 ; option 3 ; option 4 ; ... ; option n

$ awk -F';'  '{for(i=2;i<=NF;i++)gsub(" ; "," | ");print}' testfile1.txt                           
Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
    
por 11.06.2015 / 20:52
2

Você cometeu um pequeno erro:

~$ perl -00 -pe 's/;/
s/;//g;     # remove all other semicolons
s/
s/;/\n/g;     # change all other semicolons
s/
~$ perl -00 -pe 's/;/
s/;//g;     # remove all other semicolons
s/
s/;/\n/g;     # change all other semicolons
s/%pre%/;/     # restore the first semicolon
/;/ # restore the first semicolon
/; s/;/\n/g; s/%pre%/;/' file Question; option 1 option 2 option 3 option 4 ... option n
/;/ # restore the first semicolon
/;/ # restore the first semicolon
/; s/;/\n/g; s/%pre%/;/' file Question; option 1 option 2 option 3 option 4 ... option n

o que você fez:

%pre%

o que você afirmou que quer:

%pre%     
por 11.06.2015 / 14:47