Come funziona questo comando di sostituzione 'sed' con molti segni @?


8

Qualcuno può spiegare come funziona questo sedcomando?

sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"

3
Il modo normale per farlo è usare le barre, ma ciò può diventare ingombrante se cerchi e sostituisci qualcosa con le barre. Questo non è il caso qui, quindi anche se va benissimo confonde i futuri manutentori come te.
Thorbjørn Ravn Andersen,

2
... e li porta a imparare qualcosa di nuovo in sedquesto modo! :)
dessert

Risposte:


15

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@optionso s:foo:bar:g. s@+@ @gè come s/+/ /g: sostituire tutto +con spazi. Allo stesso modo s@%@\\x@gsostituisce 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+%2Fbarallora 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.


2
In breve, un decodificatore URL-> nome file.
Thorbjørn Ravn Andersen,

10

Il comando di cui stai chiedendo la decodifica di +es e %sequenze da URL non è solo un sedcomando, è una pipeline che elabora l'input sed, quindi lo reindirizza xargsper un'ulteriore elaborazione. Per prima cosa diamo un'occhiata al sedcomando:

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:

  1. s@+@ @g( s/+/ /g) sostituisce le soccorrenze ( ) di +con uno spazio. Questo influenza tutti gli +es su una linea ( g), non solo il primo.

  2. ; termina l'azione ("comando") e consente di specificarne un'altra nello stesso "script".

  3. 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 \\xla \\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 xargscomando, il cui scopo è quello di eseguire printf.

xargscostruisce 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...xargscommand...xargssed|xargs-0

Nell'uso previsto del comando, un carattere null non verrà visualizzato e xargsverrà eseguito printf %bcon un solo argomento della riga di comando aggiuntivo, l'output del sedcomando. 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 %bconsumi di formato e stampa un argomento (come %s), ma provoca fughe barra rovesciata - del genere il sedcomando 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%20printfcome input. Ottengo http://foldoc.org/debugging by printfcome output, perché le %20sequenze sono tradotte in spazi.


3

Questa è la bellezza di sed, applica i suoi paradigmi a se stesso ... Dopo il comando (come so tro 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 brrivbldi 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.


In esecuzione con l'idea criptica, questo è un comando sed valido, anche se non fa nulla di utile:sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
wjandrea,

Bello! Sì, puoi usare anche i sedcomandi come rompicapo, quanto è geniale?
Marabiloso,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.