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

8

Qualcuno può spiegare come funziona questo comando sed ?

sed '[email protected][email protected] @g;[email protected]%@\[email protected]' | xargs -0 printf "%b"
    
posta Raj 04.10.2017 - 10:13

3 risposte

15

In sed, i comandi sostitutivi sono di solito scritti come s/pattern/replacement/options . Tuttavia, non è necessario utilizzare / - puoi utilizzare altri caratteri se è conveniente, quindi potrebbe essere [email protected]@[email protected] o s:foo:bar:g . [email protected][email protected] @g è come s/+/ /g - sostituisci tutto + con spazi. Allo stesso modo [email protected]%@\[email protected] sostituisce tutto % con \x (una singola barra rovesciata è un carattere di escape in sed, quindi è necessario due per ottenere una barra rovesciata effettiva).

Una stringa come foo+%2Fbar diventerà quindi foo \x2Fbar . printf "%b" espande le sequenze di escape backslash come \x2F (il carattere ASCII il cui valore esadecimale è 2F, che è / ) per darti finalmente foo /bar .

    
risposta data muru 04.10.2017 - 10:32
10

Il comando che stai chiedendo per la decodifica + es e % sequenze dagli URL è non solo un comando sed , è una pipeline che elabora i dati con sed , quindi le canalizza in xargs per ulteriori elaborazioni. Per prima cosa guardiamo il comando sed :

sed '[email protected][email protected] @g;[email protected]%@\[email protected]'

Potresti essere più abituato a vederlo con / piuttosto che @ come separatore, che potrebbe essere facilmente eseguito qui senza complicazioni dato che / non viene visualizzato in nessuno dei pattern di ricerca né in uno dei due testi di sostituzione . Questo comando è equivalente:

sed 's/+/ /g;s/%/\x/g'

Come / , @ è un carattere di punteggiatura perfettamente buono per sed .

Su ogni riga di input:

  1. [email protected][email protected] @g ( s/+/ /g ) sostituzioni ( s ) occorrenze di + con uno spazio. Ciò riguarda tutto + es su una riga ( g ), non solo il primo.

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

  3. [email protected]%@\[email protected] ( s/%/\x/g ) sostituti ( s ) occorrenze di % con \x . Come prima, agisce su tutti anziché solo sul primo di ogni riga ( g ).

    In \x la \ rappresenta solo un \ 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 viene dopo di esso che altrimenti avrebbe un significato speciale. Quindi deve essere salvato come \ .

Ora diamo un'occhiata al comando xargs , il cui scopo è eseguire printf .

xargs costruisce righe di comando. Se esegui xargs command... , dove command... è una o più parole, xargs esegue command... con ulteriori argomenti della riga di comando letti dal suo input. In questo caso, l'input di xargs è l'output di sed , a causa della pipe ( | ). Normalmente xargs interpreta qualsiasi spazio bianco nel suo input per indicare che il testo prima e dopo costituisce argomenti separati, ma l'opzione -0 consente di dividere gli argomenti alle occorrenze di null character invece.

Nell'uso previsto del comando, un carattere nullo non apparirà e xargs eseguirà printf %b con un solo argomento riga di comando aggiuntivo, l'output di sed comando. Quindi, anche se non è equivalente in generale, in questo caso l'intera pipeline potrebbe essere stata scritta in questo modo usando sostituzione comando anziché xargs :

printf '%b\n' "$(sed 's/+/ /g;s/%/\x/g')"

Per quanto riguarda ciò che printf intende fare qui, come muru dice il L'identificatore di formato %b consuma e stampa un argomento (come %s ) ma causa l'escape dei backslash - del tipo il comando sed sul lato sinistro del pipe è stato scritto per generare - to be trascritto nei personaggi che rappresentano .

Supponiamo che eseguo quel comando e passi http://foldoc.org/debugging%20by%20printf come input. Ottengo http://foldoc.org/debugging by printf come output, perché le sequenze %20 sono tradotte in spazi.

    
risposta data Eliah Kagan 04.10.2017 - 11:31
3

Questa è la bellezza di sed , applica i suoi paradigmi a se stessa ... Dopo il comando (come s o tr o niente), il prossimo carattere è 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 così orribile come:

echo 'arrival' | sed srarbrg

... e come risultato ottieni brrivbl , 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 l'espressione contiene il delimitatore, rende più facile afferrare l'intento. Il delimitatore può essere qualsiasi cosa nell'intervallo ASCII8 (i delimitatori multibyte come £ provocano un errore).

Ricorda solo che l'obiettivo è rendere le cose più facili, non più criptici.

    
risposta data Marabiloso 04.10.2017 - 16:12

Leggi altre domande sui tag