Как вставить новую строку перед шаблоном?

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

Например,

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

вставляет новую строку за шаблоном regexp.

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

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

somevariable (012)345-6789

Должно стать

somevariable
(012)345-6789

Ответ 1

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

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

Изменить: это не работает на OS X, если вы не установите gnu-sed.

Ответ 2

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

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

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

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

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

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

Ответ 3

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

$ sed 's/regexp/\
&/'

Пример:

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

foo

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

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

foo

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

Ответ 4

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

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

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

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

Ответ 5

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

Ответ 6

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

cat Somefile |tr ',' '\012' 

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

Ответ 7

Вы можете использовать perl one-liners так же, как и с sed, с преимуществом полной поддержки регулярных выражений perl (что намного мощнее, чем то, что вы получаете с 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}

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

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

Ответ 8

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

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

Ответ 9

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

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

Где file1 было:

def

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

abc
def

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

Ответ 10

в sed вы можете ссылаться на группы в вашем шаблоне с помощью "\ 1", "\ 2",.... поэтому, если шаблон, который вы ищете, является "PATTERN", и вы хотите вставить перед ним "BEFORE", вы можете использовать, без экранирования

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

то есть.

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

Ответ 11

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

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

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

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

Ответ 12

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

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

Ответ 13

Вы также можете сделать это с помощью 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

Ответ 14

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

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

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

Ответ 15

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

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

Доно ли его идеальный...

Ответ 16

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

#!/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

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

Ответ 17

Поскольку sed в OS X может быть нечетким для расширенной подстановки, я использовал php для этого, так как он может быть вызван непосредственно из CLI с опцией -r:

php -r 'str_replace("pattern", "\npattern");'

Кроме того, php может передаваться аргументам, поэтому он отлично интегрируется в расширенный script. Здесь более надежный пример с php, встроенным в bash script, который будет выполнять подстановку непосредственно в файле:

pattern=xxx
php -r '$filePath = "/home/buzut/file"; file_put_contents($hostsFilePAth, str_replace($argv[1], "\n$argv[1]", file_get_contents($filePath)));' $pattern