Использование `sed` без многократного прокачивания - PullRequest
3 голосов
/ 11 декабря 2011

Пример:

echo one two three | sed 's/ /\n/g' | sed 's/^/:/g'

Выход:

: один
: два
: три

Без трубопровода:

echo one two three | sed 's/ /\n/g;s/^/:/g'

вывод:

: один
два
три

кажется, что первый шаблон не раскрывается до выполнения второго, но я действительно не очень разбираюсь в sed

Как использовать первый пример без двойного трубопровода?

PS Шаблон, используемый в примерах, информативен

Ответы [ 4 ]

8 голосов
/ 11 декабря 2011

Другой способ сделать это с помощью повторяющихся опций -e:

echo one two three | sed -e 's/ /\n:/g' -e 's/^/:/g'

Это легче понять, когда вам нужно выполнить много операций;Вы можете выровнять отдельные операции по отдельным строкам:

echo one two three |
sed -e 's/ /\n:/g' \
    -e 's/^/:/g'

Например, у меня есть скрипт для генерации документов схемы из шаблонов.Одна часть скрипта содержит:

sed -e "s/[:]YEAR:/$(date +%Y)/g" \
    -e "s/[:]TODAY:/$today/" \
    -e "s/[:]BASE:/$BASE/g" \
    -e "s/[:]base:/$base/g" \
    -e "s/[:]FILE:/$FILE/g" \
    -e "s/[:]file:/$file/g" \
    $skeleton |
...

Хотя это можно сделать в одну строку, это не будет способствовать удобочитаемости.

1 голос
/ 11 декабря 2011

Вы можете поместить все это в одно регулярное выражение, как это:

echo one two three | sed 's/\([^ ]\+\)\( \+\|$\)/:\1\n/g'

Первая часть \([^ ]\+\) выбирает ваши слова (то есть строку символов, которая не является пробелом. Часть секунд \( \+\|$\) соответствует одному или нескольким пробелам или концу строки (что требуется для three, в котором после него нет пробела.

Затем мы просто строим строку, используя обратную ссылку на слово, соответствующеев части 1.

1 голос
/ 11 декабря 2011

Основная проблема здесь заключается в том, что sed решает, что представляет собой строку (шаблон, с которым он работает), перед выполнением каких-либо команд. То есть, если у вас есть только один шаблон (one two three), он не будет интерпретироваться как несколько строк после выполнения s/ /\n/g. Если бы все еще был один шаблон, хотя это был бы тот, который содержал внутри него новые строки.

Самый простой обходной путь, позволяющий перераспределить шаблоны sed по вновь вставленным символам новой строки, - просто запустить sed дважды, как вы сделали.

Другим обходным решением было бы добавить что-то вроде опции m (многострочный буфер) к команде s:

$ echo one two three | sed 's/ /\n/g;s/^/:/mg'
:one
:two
:three
0 голосов
/ 11 декабря 2011

Это может работать для вас:

echo one two three | sed 'y/ /\n/;s/^/:/mg'
:one
:two
:three
...