Jak działa to polecenie zamiany „sed” z dużą ilością znaków @?

8

Czy ktoś może wyjaśnić, jak seddziała to polecenie?

sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
Raj
źródło
3
Normalnym sposobem na to jest użycie ukośników, ale może to być kłopotliwe, jeśli przeszukasz coś i zastąpisz go ukośnikiem. Tak nie jest tutaj, więc nawet jeśli jest w porządku, myli przyszłych opiekunów takich jak ty.
Thorbjørn Ravn Andersen
2
… I prowadzi ich do nauczenia się czegoś nowego na sedten temat ! :)
deser

Odpowiedzi:

15

W sed polecenia zastępcze są zwykle zapisywane jako s/pattern/replacement/options. Jednak nie jest konieczne użycie /- możesz użyć innych znaków, jeśli jest to wygodne, więc może to być s@pattern@replacement@optionslub s:foo:bar:g. s@+@ @gjest jak s/+/ /g- zamień wszystko +spacjami. Podobnie s@%@\\x@gzastępuje wszystkie %z \x(pojedynczy lewy ukośnik jest znakiem ucieczki w sed, więc trzeba dwa, aby uzyskać rzeczywistą backslash).

foo+%2FbarStanie się taki ciąg foo \x2Fbar. printf "%b"rozwinie sekwencje specjalne z odwrotnym ukośnikiem, takie jak \x2F(znak ASCII, którego wartość szesnastkowa to 2F, czyli /), aby w końcu dać ci foo /bar.

muru
źródło
2
W skrócie, dekoder URL-> nazwa pliku.
Thorbjørn Ravn Andersen
10

Polecenie, o które pytasz o dekodowanie +es i %sekwencji z adresów URL, to nie tylko sedpolecenie, to potok, który przetwarza dane wejściowe sed, a następnie przesyła je do xargsdalszego przetwarzania. Najpierw spójrzmy na sedpolecenie:

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

Możesz być bardziej przyzwyczajony do tego, że widzisz go /raczej @jako separator, co można łatwo zrobić bez komplikacji, ponieważ nie /pojawia się w żadnym wzorcu wyszukiwania ani w tekście zastępczym. To polecenie jest równoważne:

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

Podobnie jak /, @jest idealnie dobrą postacią interpunkcyjną sed.

W każdym wierszu danych wejściowych:

  1. s@+@ @g( s/+/ /g) zastępuje ( s) wystąpienia +spacją. Wpływa to na wszystkie +es na linii ( g), nie tylko na pierwszą.

  2. ; kończy działanie („polecenie”) i pozwala określić inną w tym samym „skrypcie”.

  3. s@%@\\x@g( s/%/\\x/g) zastępuje ( s) wystąpienia %z \x. Tak jak poprzednio, działa na wszystkich, a nie tylko na pierwszym wierszu ( g).

    W reprezentuje tylko jeden , ponieważ ma specjalne znaczenie . Jego szczególne znaczenie jest tak naprawdę, jak postać, której używasz, aby odebrać specjalne znaczenie kolejnej po niej postaci, która w innym przypadku miałaby specjalne znaczenie. Więc musi być jak .\\x\\\\sed\\


Teraz spójrzmy na xargspolecenie, którego celem jest uruchomienie printf.

xargsbuduje linie poleceń. Jeśli uruchomisz , gdzie jest jedno lub więcej słów, zostanie uruchomione z dodatkowymi argumentami wiersza poleceń odczytanymi z jego danych wejściowych. W tym przypadku dane wejściowe to dane wyjściowe z powodu potoku ( ). Zwykle interpretuje dowolne białe znaki na swoim wejściu, co oznacza, że ​​tekst przed i po nim stanowi osobne argumenty, ale opcja ta powoduje, że dzieli argumenty w przypadku wystąpienia znaku null .xargs command...command...xargscommand...xargssed|xargs-0

W zamierzonym użyciu polecenia znak null nie pojawi się i xargsbędzie działał printf %bz jednym dodatkowym argumentem wiersza polecenia, wynikiem sedpolecenia. Tak więc, choć ogólnie nie jest to równoważne, w tym przypadku cały potok mógł zamiast tego zostać napisany w ten sposób przy użyciu podstawiania poleceń zamiast xargs:

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

Jeśli chodzi o to, co printfma tu zostać zrobione, jak mówi muru, specyfikator %bformatu zużywa i wypisuje argument (jak %s), ale powoduje , że znaki odwrotnego ukośnika - takie jak sedpolecenie wygenerowane po lewej stronie potoku - zostało przetłumaczone w postacie, które reprezentują .

Załóżmy, że uruchamiam to polecenie i przekazuję http://foldoc.org/debugging%20by%20printfjako dane wejściowe. Otrzymuję http://foldoc.org/debugging by printfjako wynik, ponieważ %20sekwencje są tłumaczone na spacje.

Eliah Kagan
źródło
3

To piękno sed, to stosuje swoje paradygmaty do siebie ... Po wydaniu polecenia (takie jak salbo tralbo nic), następny znak jest uważany za separator.

Powinieneś mądrze wybrać, aby uniknąć ingerencji w powłokę i samą komendę oraz zachować czytelność, ale napisanie czegoś tak okropnego jak:

echo 'arrival' | sed srarbrg

... i uzyskaj brrivblw rezultacie to, czego oczekujesz. Możesz się dobrze bawić, czyniąc go naprawdę tajemniczym, na przykład:

echo 'arrival' | sed s\fa\fb\fg   # \f is form feed, chr(12)

Powszechnym zastosowaniem jest użycie ukośnika jako ogranicznika, ale gdy twoje wyrażenie zawiera ogranicznik, łatwiej jest uchwycić zamiar. Ogranicznikiem może być dowolny element z zakresu ASCII8 (ograniczniki wielobajtowe, takie jak £wywołać błąd).

Pamiętaj tylko, że celem jest uczynienie rzeczy łatwiejszymi, a nie bardziej tajemniczymi.

Marabiloso
źródło
Działa z tajemniczą ideą, jest to poprawna komenda sed, chociaż nie robi nic użytecznego:sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
wjandrea,
Miły! Tak, możesz też używać sedpoleceń jako łamigłówek, jaki to jest naukowy?
Marabiloso