Alguém pode explicar como esse sed
comando funciona?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
sed
esse caminho! :)
Alguém pode explicar como esse sed
comando funciona?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
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 ser s@pattern@replacement@options
ou s:foo:bar:g
. s@+@ @g
é como s/+/ /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
.
O comando que você está perguntando para decodificar +
es e %
sequências de URLs não é apenas um sed
comando, é um pipeline que processa a entrada sed
e a canaliza xargs
para processamento adicional. Primeiro vamos olhar para o sed
comando:
sed 's@+@ @g;s@%@\\x@g'
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
).
\\x
No \\
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 xargs
comando, cujo objetivo é executar printf
.
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á executado printf %b
com apenas um argumento de linha de comando adicional, a saída do sed
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 de xargs
:
printf '%b\n' "$(sed 's/+/ /g;s/%/\\x/g')"
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 o sed
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. Recebo http://foldoc.org/debugging by printf
como saída, porque as %20
seqüências são traduzidas em espaços.
Essa é a beleza de sed
, ela aplica seus paradigmas a si mesma ... Após o comando (como s
ou tr
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:
echo 'arrival' | sed srarbrg
... e, brrivbl
como 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.
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?