Com sed , você pode escrevê-lo como:
sed '/\([^:]*\):.*{IPA|\([^}]*\).*/!d;s// /;s,/,,g;:1
s/\(\([^ ]*\).*\)|/\n /;t1'
Divisão (por @slm, obrigado)
O comando acima pode ser dividido da seguinte forma:
-
Analise a entrada em
when: ... {IPA|...}e exclua linhas não correspondentes.Em
/pattern/!d; s//repl/Nós [d] fazemos o cartão das linhas que não [!] correspondem ao padrão, e então reutilizamos o mesmo padrão no próximo comando de substituição [s] (um padrão vazio significa reutilizar o último padrão). Em vez de [d] eletizar as linhas não correspondentes, poderíamos tê-las deixado inalteradas usando
bem vez dedou, se sabemos que todas as linhas correspondem ao padrão, poderíamos usars/pattern/repl/diretamente. / p>/\([^:]*\):.*{IPA|\([^}]*\).*/Esse padrão divide os dados em dois blocos. O primeiro pedaço é
when:. Esse código,\([^:]*\):diz para pegar todos os caracteres até encontrar um:e salvá-lo em um temp. variável ().Todos os caracteres entre o
:até e incluindo o{IPA|são ignorados. O próximo bit que é salvo é tudo depois doIPA|. Isso é feito por este bloco de código,\([^}]*\), que diz para salvar todo o código até que um}seja encontrado. Isso é salvo na variável ().OBSERVAÇÃO: Em
sedsempre que você quiser salvar um trecho da string, você poderá envolvê-lo entre parênteses. Eles precisam ser escapados com um\para quesedsaiba que você não se refere a um parêntese literal. Assim:\( savethis \).exemplo
$ sed 's/\([^:]*\):.*{IPA|\([^}]*\).*/ /;' sample.txt when /wɛn/|/ʍɛn/ -
Remover todas as barras (
/)Este parece mais complicado porque está usando um separador alternativo. Você normalmente usaria o formulário
s///g, masseddeixa os separadores na hora, então estamos usando vírgulas (s,,,g). Este bloco procura por/e substitui-os por nada.exemplo
$ sed '/\([^:]*\):.*{IPA|\([^}]*\).*/!d;s// /;s,/,,g;' sample.txt when wɛn|ʍɛn -
Iterar através de cada IPA
:1 s/\(\([^ ]*\).*\)|/\n /;t1Este é de longe o componente mais complicado desta solução. É difícil ver o que está acontecendo, mas esse bloco é um ramo condicional.
:label command(s) t labelO rótulo é
:1do (s) comando (s) sãos/\(\([^ ]*\).*\)|/\n /;e ot labelé o "teste" que vê se o comando anterior modificou o espaço do padrão. Se sim, pule para o label1, daí ot1. -
O comando dentro do loop
Se tirarmos o
label ... looppor um segundo e aumentarmos nosso exemplo de IPA para que ele tenha 3, você poderá ver o que está acontecendo um pouco melhor.{{IPA|/wɛn/|/ʍɛn/|/blah/}}Terminaremos com isso, usando os comandos anteriores até este ponto.
when wɛn|ʍɛn|blahSe agora executarmos isso:
$ echo "when wɛn|ʍɛn|blah" | sed 's/\(\([^ ]*\).*\)|/ /;'Nós recebemos isto:
when wɛn|ʍɛn when blahVocê pode ver o que está fazendo agora? Sim, eu também não, então vamos simplificar um pouco mais, pegar a nova linha (
\n) e trocar algumas strings mais curtas.exemplo mais simples
$ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/ /;' X C1|C2 X C3Agora, o que está acontecendo aqui é que o código
\(\([^ ]*\).*\)|é inteligente no sentido de que está aninhando os parênteses para que eles fiquem assim( ( ) ). O que está sendo combinado nos parênteses internos é qualquer coisa que não seja um espaço. Este get é a stringwhen. Os parens externos correspondem a tudo até o último tubo (|).A outra coisa interessante com este trecho de código é que os parens são ordenados para que os externos sejam armazenados em
enquanto os internos são. Isso ocorre porquesedos números com base na ordem em que eles são encontrados.Você pode se convencer disso estendendo o snippet com
's e' adicionais.$ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/ /;' X C1|C2 X C1|C2 X C1|C2 C3 $ echo "X C1|C2|C3" | sed 's/\(\([^ ]*\).*\)|/ /;' X C1|C2 X X CPortanto, o comando dentro do loop basicamente leva o
X2 vezes. Uma vez como parte de todo oX C1|C2(fora de parênteses) e uma segunda vez como qualquer coisa até o espaço (dentro de parênteses). -
Voltar para o ramo condicional
OK, então o branch vai basicamente chamar o comando em # 5, para IPAs onde há mais de 2.
sed's branch construct vai continuar re-executando o comando até que o comando não modifique mais a substituição, em que ponto ele pára.exemplo
$ echo "X C1|C2|C3" | sed ':1 s/\(\([^ ]*\).*\)|/\n /; t1' X C1 X C2 X C3
Espero que os itens acima ajudem outros transeuntes com essa resposta no futuro.