Как вставить новую строку перед шаблоном? - PullRequest
120 голосов
/ 07 апреля 2009

Не как вставить новую строку перед строкой. Здесь спрашивается, как вставить новую строку перед шаблоном в строке.

Например,

sed 's/regexp/&\n/g'

вставит новую строку за шаблоном регулярного выражения.

Как я могу сделать то же самое, но перед шаблоном?

Вот пример входного файла

somevariable (012)345-6789

Должен стать

somevariable
(012)345-6789

Ответы [ 16 ]

152 голосов
/ 23 июня 2012

Это работает в bash, протестировано на Linux и OS X:

sed 's/regexp/\'$'\n/g'

Как правило, для $, за которым следует строковый литерал в одинарных кавычках, bash выполняет подстановку обратной косой черты в стиле C, например, $'\t' переводится в буквальную вкладку. Кроме того, sed хочет, чтобы ваш литерал новой строки был экранирован с помощью обратной косой черты, следовательно, от \ до $. И, наконец, сам знак доллара не следует заключать в кавычки, чтобы он интерпретировался оболочкой, поэтому мы закрываем кавычку перед $ и затем открываем ее снова.

Редактировать : Как указано в комментариях @ mklement0, это также работает:

sed $'s/regexp/\\\n/g'

Здесь происходит следующее: вся команда sed теперь является строкой в ​​стиле C, что означает, что обратный слеш, который нужно поместить в sed, должен быть экранирован перед литералом новой строки с помощью другого обратного слэша. Хотя это и более читабельно, в этом случае вы не сможете выполнять подстановку строк оболочки (не сделав это снова безобразным.)

38 голосов
/ 07 апреля 2009

Некоторые другие ответы не работают для моей версии sed. Переключение позиций & и \n сработало.

sed 's/regexp/\n&/g' 

Редактировать: Похоже, это не работает на OS X, если вы не установите gnu-sed.

32 голосов
/ 07 апреля 2009

В sed вы не можете легко добавлять новые строки в выходной поток. Вам нужно использовать строку продолжения, что неудобно, но работает:

$ sed 's/regexp/\
&/'

Пример:

$ echo foo | sed 's/.*/\
&/'

foo

Подробнее см. здесь . Если вы хотите что-то немного менее неловкое, вы можете попробовать использовать perl -pe с группами совпадений вместо sed:

$ echo foo | perl -pe 's/(.*)/\n$1/'

foo

$1 относится к первой сопоставленной группе в регулярном выражении, где группы указаны в скобках.

28 голосов
/ 27 сентября 2011

На моем Mac следующее вставляет один 'n' вместо новой строки:

sed 's/regexp/\n&/g'

Это заменяет символ новой строки:

sed "s/regexp/\\`echo -e '\n\r'`/g"
14 голосов
/ 01 декабря 2012
echo one,two,three | sed 's/,/\
/g'
9 голосов
/ 20 августа 2012

В этом случае я не использую sed. Я использую tr.

cat Somefile |tr ',' '\012' 

Принимает запятую и заменяет ее на возврат каретки.

8 голосов
/ 21 мая 2014

Вы можете использовать perl one-liners так же, как и с sed, с преимуществом полной поддержки регулярного выражения perl (что намного мощнее, чем то, что вы получаете с sed). На * nix платформах также очень мало изменений - perl обычно perl. Так что вы можете перестать беспокоиться о том, как заставить версию вашей конкретной системы sed делать то, что вы хотите.

В этом случае вы можете сделать

perl -pe 's/(regex)/\n$1/'

-pe помещает perl в цикл «выполнить и напечатать», очень похожий на обычный режим работы sed.

' цитирует все остальное, чтобы оболочка не мешала

(), окружающее регулярное выражение, является оператором группировки. $1 справа от замены выводит все, что было найдено в этих скобках.

Наконец, \n - это новая строка.

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

\(\d\d\d\)\d\d\d-\d\d\d\d

\( или \) соответствует буквальному пареню, а \d соответствует цифре.

Лучше:

\(\d{3}\)\d{3}-\d{4}

Я полагаю, вы можете понять, что делают числа в фигурных скобках.

Кроме того, вы можете использовать разделители, отличные от / для вашего регулярного выражения. Так что если вам нужно соответствовать / вам не нужно избегать его. Любое из приведенного ниже эквивалентно регулярному выражению в начале моего ответа. Теоретически вы можете заменить любой символ на стандартные /.

perl -pe 's#(regex)#\n$1#'
perl -pe 's{(regex)}{\n$1}'

Дополнительный совет - если у вас установлен пакет pcre, он поставляется с pcregrep, в котором используются полностью совместимые с perl регулярные выражения.

4 голосов
/ 22 мая 2014

Хм, только что вышедшие символы новой строки работают в более свежих версиях sed (у меня GNU sed 4.2.1),

dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar
3 голосов
/ 10 декабря 2015
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'

отлично работал на El Captitan с поддержкой ()

3 голосов
/ 15 сентября 2012

Чтобы вставить новую строку в выходной поток в Linux, я использовал:

sed -i "s/def/abc\\\ndef/" file1

Где file1 было:

def

Перед заменой sed на месте и:

abc
def

После замены седла на месте. Обратите внимание на использование \\\n. Если в шаблонах есть ", убегите, используя \".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...