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
b
em vez ded
ou, 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
sed
sempre que você quiser salvar um trecho da string, você poderá envolvê-lo entre parênteses. Eles precisam ser escapados com um\
para quesed
saiba 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
, massed
deixa 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 /;t1
Este é 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 label
O rótulo é
:1
do (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 ... loop
por 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|blah
Se agora executarmos isso:
$ echo "when wɛn|ʍɛn|blah" | sed 's/\(\([^ ]*\).*\)|/ /;'
Nós recebemos isto:
when wɛn|ʍɛn when blah
Você 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 C3
Agora, 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 porque
sed
os 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 C
Portanto, o comando dentro do loop basicamente leva o
X
2 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.