Як працює ця команда заміщення 'sed' з великою кількістю знаків @?


8

Хтось може пояснити, як sedпрацює ця команда?

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

3
Нормальний спосіб зробити це за допомогою косої риски, але це може стати громіздким, якщо ви щось шукаєте і замінюєте косою рисою. Це не так, тому, хоча це абсолютно чудово, це бентежить майбутніх технічних працівників, як ви.
Thorbjørn Ravn Andersen

2
… І веде їх дізнатися щось нове про sedцей спосіб! :)
десерт

Відповіді:


15

У sed команди, що замінюють, зазвичай записуються як s/pattern/replacement/options. Однак використовувати це не обов’язково /- ви можете використовувати інші символи, якщо це зручно, так це могло бути s@pattern@replacement@optionsабо s:foo:bar:g. s@+@ @gце як s/+/ /g- замінити все +пробілами. Аналогічно s@%@\\x@gзамінює все %на \x(один зворотний косий рядок є символом втечі в sed, тому вам потрібно два, щоб отримати фактичний зворотний кут).

Тоді такий рядок foo+%2Fbarстане foo \x2Fbar. printf "%b"розширить схожі послідовності на зразок \x2F(символ ASCII, шістнадцяткове значення якого становить 2F, тобто /), нарешті, дасть вам foo /bar.


2
Якщо коротко, URL-> декодер імені файлу.
Thorbjørn Ravn Andersen

10

Команда, про яку ви просите розшифрувати +es та %послідовності з URL-адрес, - це не просто sedкоманда, це конвеєр, який обробляє вхід sed, а потім передає його xargsдля подальшої обробки. Спочатку давайте подивимось на sedкоманду:

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

Ви можете бути більш звикли бачити це /не @як роздільник, що легко можна було б зробити тут без ускладнень, оскільки не /з'являється в жодному з шаблонів пошуку, ані в жодному із текстів заміни. Ця команда рівнозначна:

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

Мовляв /, @ідеально хороший розділовий символ для sed.

У кожному рядку введення:

  1. s@+@ @g( s/+/ /g) замінює ( s) входження +з пробілом. Це впливає на всі +es у рядку ( g), а не лише на першому.

  2. ; завершує дію ("команда") і дозволяє вказати ще одну в тому ж "скрипті".

  3. s@%@\\x@g( s/%/\\x/g) замінники ( s) виникнення %с \x. Як і раніше, він діє на всі, а не лише на перший з кожного рядка ( g).

    В представляє тільки один , тому що має особливе значення для . Його особливий сенс насправді як персонаж, який ви використовуєте, щоб забрати особливе значення іншого персонажа, що приходить після нього, яке б інакше мало особливе значення. Тому його треба уникати як .\\x\\\\sed\\


Тепер розглянемо xargsкоманду, мета якої - запустити printf.

xargsбудує командні рядки. Якщо ви запустите , де є одне або декілька слів, виконуються з додатковими аргументами командного рядка, прочитаними з його введення. У цьому випадку вхід до - це вихід , через трубу ( ). Зазвичай інтерпретує будь-який пробіл у своєму введенні, щоб означати, що текст до та після нього становить окремі аргументи, але параметр змушує його розділяти аргументи на місцях появи нульового символу .xargs command...command...xargscommand...xargssed|xargs-0

При використанні команди, призначене для використання, нульовий символ не з’явиться і xargsбуде працювати printf %bлише з одним додатковим аргументом командного рядка, висновком sedкоманди. Таким чином, хоч і не є рівнозначним загалом, у цьому випадку весь конвеєр може бути написаний таким чином, використовуючи заміну команди замість xargs:

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

Що ж стосується того, що printfпередбачається зробити тут, в Мурі говорить про %bформаті специфікатор споживає і друкує аргумент (наприклад %s) , але викликає зворотний слеш - від сортування по sedкоманді на лівій стороні труби була написано для створення - бути переведено в символи, які вони представляють .

Припустимо, я запускаю цю команду і передаю http://foldoc.org/debugging%20by%20printfяк вхід. Я отримую http://foldoc.org/debugging by printfяк вихід, тому що %20послідовності перекладаються на пробіли.


3

Це краса sed, вона застосовує свої парадигми до себе ... Після команди (наприклад, sчи , trабо нічого), то наступний символ вважається роздільником.

Вам слід вибрати розумно, щоб уникнути втручання в оболонку та саму команду, і тримати річ читабельною, але цілком справедливо написати щось таке жахливе, як:

echo 'arrival' | sed srarbrg

... і отримуйте brrivblрезультат, якого ви очікуєте. Ви можете розважитися, зробивши це по-справжньому виразним, як-от у:

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

Загальне використання - використовувати косу рису в якості роздільника, але коли ваш вираз містить роздільник, це полегшує розуміння того, що є наміром. Вашим роздільником може бути що завгодно в діапазоні ASCII8 (багатобайтові роздільники, такі як £спровокувати помилку).

Просто пам’ятайте, мета - зробити речі простішими, а не більш виразними.


Працюючи з криптовалютою, це дійсна команда sed, хоча вона нічого корисного не робить:sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
wjandrea

Приємно! Так, ви можете використовувати sedкоманди і як тизери для мозку, наскільки вигідний це?
Marabiloso
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.