Quelqu'un peut-il expliquer comment cette sed
commande fonctionne?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
sed
ce chemin! :)
Quelqu'un peut-il expliquer comment cette sed
commande fonctionne?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
sed
ce chemin! :)
Réponses:
Dans sed, les commandes de substitution sont généralement écrites sous la forme s/pattern/replacement/options
. Cependant, il n'est pas nécessaire d'utiliser /
- vous pouvez utiliser d'autres caractères si cela vous convient, ce pourrait donc être s@pattern@replacement@options
ou s:foo:bar:g
. s@+@ @g
c'est comme s/+/ /g
- remplacer tout +
par des espaces. De même s@%@\\x@g
remplace tous %
avec \x
(une seule barre oblique inverse est un caractère d'échappement à sed, vous avez donc besoin de deux pour obtenir une barre oblique inverse réelle).
Une chaîne comme foo+%2Fbar
deviendra alors foo \x2Fbar
. printf "%b"
étendra les séquences échappées par une barre oblique inverse comme \x2F
(le caractère ASCII dont la valeur hexadécimale est 2F, qui est /
) pour enfin vous donner foo /bar
.
La commande pour laquelle vous demandez le décodage des +
es et des %
séquences des URL n'est pas seulement une sed
commande, c'est un pipeline qui traite les entrées avec sed
, puis les redirige vers xargs
un traitement ultérieur. Voyons d'abord la sed
commande:
sed 's@+@ @g;s@%@\\x@g'
Vous pouvez être plus habitué à le voir avec /
plutôt que @
comme séparateur, ce qui aurait facilement pu être fait ici sans complication car il /
n'apparaît dans aucun des modèles de recherche ni dans aucun des textes de remplacement. Cette commande est équivalente:
sed 's/+/ /g;s/%/\\x/g'
Comme /
, @
est un caractère de ponctuation parfaitement bon pour sed
.
Sur chaque ligne d'entrée:
s@+@ @g
( s/+/ /g
) substitue ( s
) les occurrences de +
avec un espace. Cela affecte tous les +
es sur une ligne ( g
), pas seulement le premier.
;
termine l'action ("commande") et vous permet d'en spécifier une autre dans le même "script".
s@%@\\x@g
( s/%/\\x/g
) substitue ( s
) les occurrences de %
avec \x
. Comme précédemment, il agit sur tous plutôt que sur la première de chaque ligne ( g
).
Dans \\x
le \\
représente un seul \
car \
a une signification particulière pour sed
. Sa signification spéciale est en fait le personnage que vous utilisez pour enlever la signification spéciale d'un autre personnage qui vient après lui qui aurait autrement une signification spéciale. Il faut donc échapper comme \\
.
Regardons maintenant une xargs
commande dont le but est de s'exécuter printf
.
xargs
construit des lignes de commande. Si vous exécutez , où est un ou plusieurs mots, s'exécute avec des arguments de ligne de commande supplémentaires lus à partir de son entrée. Dans ce cas, l'entrée de est la sortie de , en raison de pipe ( ). Interprète normalement tout espace dans son entrée pour signifier que le texte avant et après il constitue des arguments séparés, mais l' option le fait fractionner les arguments à la place du caractère nul .xargs command...
command...
xargs
command...
xargs
sed
|
xargs
-0
Dans l'utilisation prévue de votre commande, un caractère nul n'apparaîtra pas et xargs
s'exécutera printf %b
avec un seul argument de ligne de commande supplémentaire, la sortie de la sed
commande. Ainsi, bien qu'il ne soit pas équivalent en général, dans ce cas, l'ensemble du pipeline aurait pu être écrit comme ceci en utilisant la substitution de commandes au lieu de xargs
:
printf '%b\n' "$(sed 's/+/ /g;s/%/\\x/g')"
Quant à ce qui printf
est prévu ici, comme le dit muru, le %b
spécificateur de format consomme et imprime un argument (comme %s
) mais provoque des échappements de barre oblique inverse - du type que la sed
commande sur le côté gauche du tuyau a été écrit pour générer - à traduire dans les personnages qu'ils représentent .
Supposons que j'exécute cette commande et passe http://foldoc.org/debugging%20by%20printf
en entrée. J'obtiens http://foldoc.org/debugging by printf
en sortie, car les %20
séquences sont traduites en espaces.
C'est la beauté de sed
, il applique ses paradigmes à lui-même ... Après la commande (comme s
ou tr
ou rien), le personnage suivant est considéré comme le séparateur.
Vous devez choisir judicieusement pour éviter les interférences avec le shell et la commande elle-même, et garder la chose lisible, mais il est parfaitement valable d'écrire quelque chose d'aussi horrible que:
echo 'arrival' | sed srarbrg
... et obtenez brrivbl
en conséquence, ce que vous attendez. Vous pouvez vous amuser à le rendre vraiment cryptique, comme dans:
echo 'arrival' | sed s\fa\fb\fg # \f is form feed, chr(12)
L'utilisation courante consiste à utiliser la barre oblique comme délimiteur, mais lorsque votre expression contient le délimiteur, il est plus facile de saisir l'intention. Votre délimiteur peut être n'importe quoi dans la plage ASCII8 (délimiteurs multi-octets tels que £
provoquer une erreur).
N'oubliez pas que l'objectif est de rendre les choses plus faciles, pas plus cryptiques.
sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
sed
commandes comme casse-tête, comment est-ce geek?