Qualcuno può spiegare come funziona questo sed
comando?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
sed
questo modo! :)
Qualcuno può spiegare come funziona questo sed
comando?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
sed
questo modo! :)
Risposte:
In sed, i comandi sostitutivi sono generalmente scritti come s/pattern/replacement/options
. Tuttavia, non è necessario utilizzare /
: puoi usare altri caratteri se è conveniente, quindi potrebbe essere s@pattern@replacement@options
o s:foo:bar:g
. s@+@ @g
è come s/+/ /g
: sostituire tutto +
con spazi. Allo stesso modo s@%@\\x@g
sostituisce tutto %
con \x
(una singola barra rovesciata è un personaggio di escape in sed, quindi ne occorrono due per ottenere una barra rovesciata effettiva).
Una stringa come foo+%2Fbar
allora diventerà foo \x2Fbar
. printf "%b"
espanderà le sequenze con escape della barra rovesciata come \x2F
(il carattere ASCII il cui valore esadecimale è 2F, che è /
) per darti finalmente foo /bar
.
Il comando di cui stai chiedendo la decodifica di +
es e %
sequenze da URL non è solo un sed
comando, è una pipeline che elabora l'input sed
, quindi lo reindirizza xargs
per un'ulteriore elaborazione. Per prima cosa diamo un'occhiata al sed
comando:
sed 's@+@ @g;s@%@\\x@g'
Potresti essere più abituato a vederlo con /
piuttosto che @
come un separatore, cosa che avrebbe potuto facilmente essere fatto qui senza complicazioni poiché non /
appare in nessuno degli schemi di ricerca né in nessuno dei testi sostitutivi. Questo comando è equivalente:
sed 's/+/ /g;s/%/\\x/g'
Ad esempio /
, @
è un ottimo carattere di punteggiatura per sed
.
Su ciascuna riga di input:
s@+@ @g
( s/+/ /g
) sostituisce le s
occorrenze ( ) di +
con uno spazio. Questo influenza tutti gli +
es su una linea ( g
), non solo il primo.
;
termina l'azione ("comando") e consente di specificarne un'altra nello stesso "script".
s@%@\\x@g
( s/%/\\x/g
) sostituisce ( s
) occorrenze di %
con \x
. Come prima, agisce su tutto piuttosto che solo sulla prima di ogni riga ( g
).
Nella \\x
la \\
rappresenta solo \
perché \
ha un significato speciale per sed
. Il suo significato speciale è in realtà il personaggio che usi per togliere il significato speciale di un altro personaggio che lo segue che altrimenti avrebbe un significato speciale. Quindi deve essere evaso come \\
.
Ora diamo un'occhiata al xargs
comando, il cui scopo è quello di eseguire printf
.
xargs
costruisce le righe di comando. Se si esegue , dove è una o più parole, viene eseguito con argomenti della riga di comando aggiuntivi letti dal suo input. In questo caso, l'ingresso è l'uscita di , a causa del tubo ( ). Normalmente interpreta qualsiasi spazio bianco nel suo input per indicare che il testo prima e dopo costituisce argomenti separati, ma l' opzione lo rende invece diviso argomenti in occorrenze del carattere null .xargs command...
command...
xargs
command...
xargs
sed
|
xargs
-0
Nell'uso previsto del comando, un carattere null non verrà visualizzato e xargs
verrà eseguito printf %b
con un solo argomento della riga di comando aggiuntivo, l'output del sed
comando. Pertanto, sebbene non equivalente in generale, in questo caso l'intera pipeline potrebbe invece essere stata scritta in questo modo usando la sostituzione dei comandi anziché xargs
:
printf '%b\n' "$(sed 's/+/ /g;s/%/\\x/g')"
Quanto a ciò che printf
è destinato a fare qui, come dice Muru i %b
consumi di formato e stampa un argomento (come %s
), ma provoca fughe barra rovesciata - del genere il sed
comando sul lato sinistro del tubo è stato scritto per generare - per essere tradotto nei personaggi che rappresentano .
Supponiamo di eseguire quel comando e passare http://foldoc.org/debugging%20by%20printf
come input. Ottengo http://foldoc.org/debugging by printf
come output, perché le %20
sequenze sono tradotte in spazi.
Questa è la bellezza di sed
, applica i suoi paradigmi a se stesso ... Dopo il comando (come s
o tr
o niente), il personaggio successivo viene considerato il separatore.
Dovresti scegliere saggiamente per evitare interferenze con la shell e il comando stesso e mantenere la cosa leggibile, ma è perfettamente valido scrivere qualcosa di orribile come:
echo 'arrival' | sed srarbrg
... e ottieni brrivbl
di conseguenza, che è quello che ti aspetti. Puoi divertirti a renderlo davvero criptico, come in:
echo 'arrival' | sed s\fa\fb\fg # \f is form feed, chr(12)
L'uso comune è usare la barra come delimitatore, ma quando la tua espressione contiene il delimitatore, rende più semplice afferrare quale sia l'intento. Il delimitatore può essere qualsiasi cosa nell'intervallo ASCII8 (delimitatori multibyte come £
provocare un errore).
Ricorda solo che l'obiettivo è rendere le cose più facili, non più criptiche.
sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
sed
comandi come rompicapo, quanto è geniale?