2009-04-06 4 views
105

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

Например,

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

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

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

Ниже приведен пример входного файла

somevariable (012)345-6789 

должны стать

somevariable 
(012)345-6789 
+1

Это плохой вопрос (ответ «просто переключить порядок»), но случайно вызвал хорошее обсуждение новых строк в sed! –

+0

@NilsvonBarth вопрос намного более общий и сложный, чем кажется на первый взгляд. Ответ в некоторых случаях не так прост, как переключение порядка, как вы можете видеть из многих ответов. – Dennis

+2

Нет, буквальный вопрос прост: вы спрашиваете: «sed 's/regexp/& \ n/g' вставляет новую строку за шаблоном регулярного выражения. Как я могу сделать то же самое, но перед шаблоном? " , на который ответ, который вы даете себе, является «переключить заказ». Если & \ n работает для after, тогда \ n & работает раньше. * Общий * вопрос о том, как обращаться с новыми строками в sed, сложный и хороший, но * конкретный * вопрос прост и плох. –

ответ

35

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

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

Edit: Это, кажется, не работает на OS X, если вы не установите gnu-sed.

+4

Я не уверен, что это работает во всех версиях sed. Я попробовал это на своем Mac, а \ n просто получает вывод как «n» – tgamblin

+2

Провел 15 минут на маке на моей работе, прежде чем читать свой ответ. Пойдите Apple! – Rick77

+1

Для тех, кто использует доморощенный: 'brew install gnu-sed', за которым следует' gsed 's/regexp/\ n &/g'' – aaaaaa

28

В СЕПГ, вы не можете добавлять новые строки в выходном потоке легко. Вы должны использовать продолженную линию, которая является неуклюжим, но это работает:

$ sed 's/regexp/\ 
&/' 

Пример:

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

foo 

here Посмотреть подробности. Если вы хотите что-то чуть-чуть меньше неловко вы можете попробовать использовать perl -pe с спичечных группами вместо СЭД:

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

foo 

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

+0

Почему вы говорите, что не можете добавлять новые строки? Вы можете просто сделать sed 's/regexp/& \ n/g' Вот и все – Andres

+2

Это наименее опасная вещь, которую вы можете сделать на Mac для вставки новой строки (\ n не работает на Mac) – Pylinux

+0

Perl-версия может быть изменена, чтобы сделать редактирование 'perl -pi -e 's/(. *)/\ n $ 1 /' foo' – Eponymous

1

в sed вы можете ссылаться на группы в вашем шаблоне с «\ 1», «\ 2», .... , так что если шаблон, который вы ищете, является «PATTERN», и вы хотите вставить «ПЕРЕД "перед ним, вы можете использовать, без спасаясь

sed 's/(PATTERN)/BEFORE\1/g' 

т.е.

sed 's/\(PATTERN\)/BEFORE\1/g' 
+0

На самом деле это не работает для вставки новой строки. Попробуй. – tgamblin

+0

Только что сделал: содержимое тестового файла = «ABC ABC ABC». Ran «sed» s/\\ (ABC \\)/\ n \ 1/g 'testfile, получил новые строки. Поэкспериментируйте с экранами, попробуйте добавить по одной штуке одновременно к вашему шаблону, например, убедитесь, что вы сопоставляя шаблон, затем проверяем соответствие группы, затем добавляем проверку новой строки. –

+0

Я просто попытался именно так и получил «nABC nABC nABC». Вы используете какую-то другую версию sed? – tgamblin

27

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

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

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

sed "s/regexp/\\`echo -e '\n\r'`/g" 
+0

Я делал встроенное редактирование 'sed -i' '-e ...' и имел проблемы с помощью '^ M' каретки M (ctrl + m), которые записываются в файл. Я закончил тем, что использовал perl с теми же параметрами. –

+2

Обратите внимание на то, что второй код вставляет специальный код новой строки LF CR (обратная сторона MS-DOS CR LF)! Оба Unix-подобных ОС и Mac OS X используют только LF ('\ n'). – pabouk

+0

Что-то еще в моем выражении sed вызывало столько несчастья (несмотря на то, что он отлично работал без «эха ...» и новой строки), что я просто сделал это в vim. –

1
sed -e 's/regexp/\0\n/g' 

\ 0 является нуль, поэтому ваше выражение заменяется нулевым (ничего), а затем ...
\ n является новая строка

В некоторых вариантах Unix не работает, но я думаю, что это решение вашей проблемы.

echo "Hello" | sed -e 's/Hello/\0\ntmow/g' 
Hello 
tmow 
+1

Не работает в Mac OS –

124

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

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

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

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

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

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

+3

Это дает мне «неописуемую новую строку внутри шаблона замещения» на OSX. –

+0

@Matt Gibson это очень странно, потому что «unescaped newline» дается только тогда, когда у вас есть настоящая новая строка без обратного слэша в шаблоне замещения. Мой код выше работает, по сути, и в некоторых других оболочках, например, zsh, ksh. – mojuba

+2

@Matt Gibson ... или если вы забыли обратную косую черту перед '$' \ n в моем коде. – mojuba

8

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

cat Somefile |tr ',' '\012' 

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

+0

Я нашел, что это также работает: 'cat Somefile | tr ',' '\ n'' YMMV –

3

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

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

Где file1 был:

def 

Перед SED в месте замены, а также:

abc 
def 

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

+0

для меня (Bash внутри Linux) \\ n работает так же хорошо. –

+0

Для меня код выше не работает. 'sed' вставляет' \ n' вместо LF, потому что он получает '\\ n' в параметре из оболочки. --- Этот код работает: 'sed -i 's/def/abc \ ndef /" file1'. --- 'GNU sed version 4.2.1',' GNU bash, версия 4.1.2 (1)/4.2.25 (1) '(CentOS release 6.4/Ubuntu 12.04.3). – pabouk

0

В vi на Red Hat я смог вставить каретки с использованием только символа \ r. Я считаю, что это внутренне выполняет «ex» вместо «sed», но похоже, и vi может быть другим способом делать массовые изменения, такие как исправления кода. Например. Я окружая слово для поиска с, если утверждением, что настаивает на возврате каретки после фигурных скобок:

:.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/ 

Обратите внимание, что я бы это вставить некоторые вкладки, чтобы сделать вещи лучше выровнять.

12
echo one,two,three | sed 's/,/\ 
/g' 
+0

+1 работал отлично и красиво stright-forward/easy-to-remember – gMale

+2

Этот ответ на самом деле является ** sed ** решением, а не ** bash ** решением. Все, что использует конструкции типа '$ '\ n'', полагается на оболочку для генерации новой строки. Такие решения могут быть не переносимыми. Этот. Конечно, это также дубликат второго примера в ответе tgamblin от 2009 года. – ghoti

0

Это работает в MAC для меня

sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt 

Доно ли его совершенным ...

5

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

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

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

-pe ставит Perl в «выполнить и печать» цикла, так же, как СЕПГ нормальный режим работы.

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

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

И, наконец, \n - это символ новой строки.

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

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

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

Лучше:

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

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

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

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

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

+0

Я думаю, что я закончил с sed, это отлично поработало! –

4

Хм, просто сбежал новой строки, кажется, работают в более поздних версиях sed (я GNU СЭД 4.2.1),

dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;' 
foo 
bar 
+0

Как уже упоминалось, это работает с различными версиями GNU sed, но не с sed, включенным в macOS. –

1
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/' 

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

1

Прочитав все ответы на этот вопрос, мне все же потребовалось много попыток получить правильный синтаксис в следующем примере:

#!/bin/bash 
# script: add_domain 
# using fixed values instead of command line parameters $1, $2 
# to show typical variable values in this example 
ipaddr="127.0.0.1" 
domain="example.com" 
# no need to escape $ipaddr and $domain values if we use separate quotes. 
sudo sed -i '$a \\n'"$ipaddr www.$domain $domain" /etc/hosts 

Сценарий добавляет новую строку \n, а затем другую строку текста в конец файла, используя одну команду sed.

1

Вы также можете сделать это с AWK, используя -v предоставить образец:

awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file 

Проверяется, если строка содержит заданный шаблон. Если это так, она добавляет новую строку в начало.

См базовый пример:

$ cat file 
hello 
this is some pattern and we are going ahead 
bye! 
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file 
hello 
this is some 
pattern and we are going ahead 
bye! 

Примечание это будет влиять на все шаблоны в строке:

$ cat file 
this pattern is some pattern and we are going ahead 
$ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' d 
this 
pattern is some 
pattern and we are going ahead