A maneira normal de fazer isso é usar barras, mas isso pode se tornar complicado se você pesquisar e substituir algo por barras. Esse não é o caso aqui, portanto, mesmo estando perfeitamente bem, confunde futuros mantenedores como você.
Thorbjørn Ravn Andersen
2
… E os leva a aprender algo novo sobre sedesse caminho! :)
dessert
Respostas:
15
No sed, comandos substitutos geralmente são escritos como s/pattern/replacement/options. No entanto, não é necessário usar /- você pode usar outros caracteres, se for conveniente, para que possa ser s@pattern@replacement@optionsou s:foo:bar:g. s@+@ @gé como s/+/ /g- substitua tudo +por espaços. Da mesma forma, s@%@\\x@gsubstitui todos %por \x(uma única barra invertida é um caractere de escape no sed, então você precisa de dois para obter uma barra invertida real).
Uma string como foo+%2Fbarse tornará foo \x2Fbar. printf "%b"expandirá as seqüências com escape de barra invertida como \x2F(o caractere ASCII cujo valor hexadecimal é 2F, o que é /) para finalmente fornecer a você foo /bar.
Você pode estar mais acostumado a vê-lo /do que @como separador, o que poderia facilmente ter sido feito aqui sem complicações, pois não /aparece nos padrões de pesquisa nem nos textos de substituição. Este comando é equivalente:
sed 's/+/ /g;s/%/\\x/g'
Como /, @é um caractere de pontuação perfeitamente bom para sed.
Em cada linha de entrada:
s@+@ @g( s/+/ /g) substitui ( s) ocorrências de +por um espaço. Isso afeta todos os +es em uma linha ( g), não apenas o primeiro.
; finaliza a ação ("comando") e permite que você especifique outra no mesmo "script".
s@%@\\x@g( s/%/\\x/g) substitui ( s) ocorrências de %com \x. Como antes, ele atua em todos, e não apenas no primeiro de cada linha ( g).
\\xNo \\representa apenas um \, porque \tem um significado especial para sed. Seu significado especial é, na verdade, o personagem que você usa para remover o significado especial de outro personagem que vem depois dele que, de outra forma, teria um significado especial. Portanto, deve ser escapado como \\.
Agora vamos dar uma olhada no xargscomando, cujo objetivo é executar printf.
xargsconstrói linhas de comando. Se você executar , onde houver uma ou mais palavras, será executado com argumentos adicionais da linha de comando lidos a partir de sua entrada. Nesse caso, a entrada para é a saída de , por causa do pipe ( ). Normalmente interpreta qualquer espaço em branco em sua entrada para significar que o texto antes e depois constitui argumentos separados, mas a opção faz com que ele divida argumentos em ocorrências do caractere nulo .xargs command...command...xargscommand...xargssed|xargs-0
No uso pretendido do seu comando, um caractere nulo não aparecerá e xargsserá executado printf %bcom apenas um argumento de linha de comando adicional, a saída do sedcomando. Portanto, embora não seja equivalente em geral, nesse caso, o pipeline inteiro pode ter sido escrito assim usando substituição de comando em vez de xargs:
printf '%b\n'"$(sed 's/+/ /g;s/%/\\x/g')"
Quanto ao que printfse pretende fazer aqui, como muru diz que o %bespecificador de formato consome e imprime um argumento (como %s), mas causa escapes de barra invertida - do tipo que o sedcomando no lado esquerdo do pipe foi escrito para gerar - a ser traduzido nos personagens que eles representam .
Suponha que eu execute esse comando e passe http://foldoc.org/debugging%20by%20printfcomo entrada. Recebo http://foldoc.org/debugging by printfcomo saída, porque as %20seqüências são traduzidas em espaços.
Essa é a beleza de sed, ela aplica seus paradigmas a si mesma ... Após o comando (como sou trou nada), o próximo caractere é considerado o separador.
Você deve escolher sabiamente evitar interferência com o shell e o próprio comando, e manter a legibilidade, mas é perfeitamente válido escrever algo tão horrível quanto:
echo 'arrival' | sed srarbrg
... e, brrivblcomo resultado, é o que você espera. Você pode se divertir, tornando-o realmente enigmático, como em:
echo 'arrival' | sed s\fa\fb\fg # \f is form feed, chr(12)
O uso comum é usar a barra como delimitador, mas quando sua expressão contém o delimitador, fica mais fácil capturar qual é a intenção. Seu delimitador pode ser qualquer coisa no intervalo ASCII8 (delimitadores multibyte, como £provocam um erro).
Lembre-se de que o objetivo é tornar as coisas mais fáceis, não mais enigmáticas.
Correndo com a idéia enigmática, este é um comando sed válido, embora ele não faz nada de útil:sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
wjandrea
Agradável! Sim, você também pode usar sedcomandos como quebra-cabeças, o quão nerd é isso?
sed
esse caminho! :)Respostas:
No sed, comandos substitutos geralmente são escritos como
s/pattern/replacement/options
. No entanto, não é necessário usar/
- você pode usar outros caracteres, se for conveniente, para que possa sers@pattern@replacement@options
ous:foo:bar:g
.s@+@ @g
é comos/+/ /g
- substitua tudo+
por espaços. Da mesma forma,s@%@\\x@g
substitui todos%
por\x
(uma única barra invertida é um caractere de escape no sed, então você precisa de dois para obter uma barra invertida real).Uma string como
foo+%2Fbar
se tornaráfoo \x2Fbar
.printf "%b"
expandirá as seqüências com escape de barra invertida como\x2F
(o caractere ASCII cujo valor hexadecimal é 2F, o que é/
) para finalmente fornecer a vocêfoo /bar
.fonte
O comando que você está perguntando para decodificar
+
es e%
sequências de URLs não é apenas umsed
comando, é um pipeline que processa a entradased
e a canalizaxargs
para processamento adicional. Primeiro vamos olhar para osed
comando:Você pode estar mais acostumado a vê-lo
/
do que@
como separador, o que poderia facilmente ter sido feito aqui sem complicações, pois não/
aparece nos padrões de pesquisa nem nos textos de substituição. Este comando é equivalente:Como
/
,@
é um caractere de pontuação perfeitamente bom parased
.Em cada linha de entrada:
s@+@ @g
(s/+/ /g
) substitui (s
) ocorrências de+
por um espaço. Isso afeta todos os+
es em uma linha (g
), não apenas o primeiro.;
finaliza a ação ("comando") e permite que você especifique outra no mesmo "script".s@%@\\x@g
(s/%/\\x/g
) substitui (s
) ocorrências de%
com\x
. Como antes, ele atua em todos, e não apenas no primeiro de cada linha (g
).\\x
No\\
representa apenas um\
, porque\
tem um significado especial parased
. Seu significado especial é, na verdade, o personagem que você usa para remover o significado especial de outro personagem que vem depois dele que, de outra forma, teria um significado especial. Portanto, deve ser escapado como\\
.Agora vamos dar uma olhada no
xargs
comando, cujo objetivo é executarprintf
.xargs
constrói linhas de comando. Se você executar , onde houver uma ou mais palavras, será executado com argumentos adicionais da linha de comando lidos a partir de sua entrada. Nesse caso, a entrada para é a saída de , por causa do pipe ( ). Normalmente interpreta qualquer espaço em branco em sua entrada para significar que o texto antes e depois constitui argumentos separados, mas a opção faz com que ele divida argumentos em ocorrências do caractere nulo .xargs command...
command...
xargs
command...
xargs
sed
|
xargs
-0
No uso pretendido do seu comando, um caractere nulo não aparecerá e
xargs
será executadoprintf %b
com apenas um argumento de linha de comando adicional, a saída dosed
comando. Portanto, embora não seja equivalente em geral, nesse caso, o pipeline inteiro pode ter sido escrito assim usando substituição de comando em vez dexargs
:Quanto ao que
printf
se pretende fazer aqui, como muru diz que o%b
especificador de formato consome e imprime um argumento (como%s
), mas causa escapes de barra invertida - do tipo que osed
comando no lado esquerdo do pipe foi escrito para gerar - a ser traduzido nos personagens que eles representam .Suponha que eu execute esse comando e passe
http://foldoc.org/debugging%20by%20printf
como entrada. Recebohttp://foldoc.org/debugging by printf
como saída, porque as%20
seqüências são traduzidas em espaços.fonte
Essa é a beleza de
sed
, ela aplica seus paradigmas a si mesma ... Após o comando (comos
outr
ou nada), o próximo caractere é considerado o separador.Você deve escolher sabiamente evitar interferência com o shell e o próprio comando, e manter a legibilidade, mas é perfeitamente válido escrever algo tão horrível quanto:
... e,
brrivbl
como resultado, é o que você espera. Você pode se divertir, tornando-o realmente enigmático, como em:O uso comum é usar a barra como delimitador, mas quando sua expressão contém o delimitador, fica mais fácil capturar qual é a intenção. Seu delimitador pode ser qualquer coisa no intervalo ASCII8 (delimitadores multibyte, como
£
provocam um erro).Lembre-se de que o objetivo é tornar as coisas mais fáceis, não mais enigmáticas.
fonte
sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
sed
comandos como quebra-cabeças, o quão nerd é isso?