Вставьте несколько строк текста перед конкретной строкой, используя sed

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

sed -r -i '/Line to insert after/ i Line one to insert \\
    second new line to insert \\
    third new line to insert' /etc/directory/somefile.txt

Сообщение об ошибке:

sed: -e expression #1, char 77: unterminated `s' command

Я пробовал, используя \n, \\ (как в примере), без символов вообще, просто перемещая вторую строку к следующей строке. Я также попробовал что-то вроде:

sed -r -i -e '/Line to insert after/ i Line one to insert'
    -e 'second new line to insert'
    -e 'third new line to insert' /etc/directory/somefile.txt

РЕДАКТИРОВАТЬ!: Извинения, я хотел, чтобы текст был вставлен ДО существующего, а не после!

6 ответов

Решение

Это должно работать:

sed -i '/Line to insert after/ i Line one to insert \
second new line to insert \
third new line to insert' file

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

Чтобы вставить перед строкой:

awk '
/Line to insert before/ {
    print "Line one to insert"
    print "second new line to insert"
    print "third new line to insert"
}
{ print }
' /etc/directory/somefile.txt

Чтобы вставить после строки:

awk '
{ print }
/Line to insert after/ {
    print "Line one to insert"
    print "second new line to insert"
    print "third new line to insert"
}
' /etc/directory/somefile.txt

На MacO мне нужно было еще несколько вещей.

  • Двойная обратная косая черта после i
  • Пустые кавычки после -i указать не резервный файл
  • Ведущие обратные слеши, чтобы добавить ведущие пробелы
  • Конечные двойные обратные слэши для добавления новых строк

Этот код ищет первый экземпляр </plugins в pom.xml и вставляет другой объект XML, непосредственно предшествующий ему, разделенный символом новой строки.

sed -i '' "/\<\/plugins/ i \\
\            <plugin>\\
\                <groupId>org.apache.maven.plugins</groupId>\\
\                <artifactId>maven-source-plugin</artifactId>\\
\                <executions>\\
\                    <execution>\\
\                        <id>attach-sources</id>\\
\                        <goals>\\
\                            <goal>jar</goal>\\
\                        </goals>\\
\                    </execution>\\
\                </executions>\\
\            </plugin>\\
" pom.xml

Когда строки для вставки являются результатом некоторой команды "mycmd" (например, cat results.txt или же printf "%s\n" line{1..3}), ты можешь сделать

sed -i 's/Line to insert after/r' <(cmd) file
or 
sed -i 's/Line to insert after/echo "&";cmd/e' file

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

Это будет работать с первой строки. Например: если вы хотите вставить из третьей строки файла, замените "1i" на "3i".

sed -i '1i line1'\\n'line2'\\n'line3' 1.txt 

cat 1.txt

 line1
 line2
 line3
 Hai

Чтобы быть POSIX-совместимым и работать в OS X, я использовал следующее (строка в одинарных кавычках и пустая строка для демонстрационных целей):

sed -i "" "/[pattern]/i\\
line 1\\
line 2\\
\'line 3 with single quotes\`
\\
" <filename>
sed -i '/Line to insert after/ i\
Line one to insert\
second new line to insert\
third new line to insert' /etc/directory/somefile.txt

Это можно легко сделать с помощью Perl.

$ cat MeanwhileInHell.txt
Iran|XXXXXX|Iranian
Iraq|YYYYYY|Iraquian
Saudi|ZZZZZ|Saudi is a Rich Country
USA|AAAAAA|USA is United States of America.
India|IIII|India got freedom from British.
Scot|SSSSS|Canada Mexio.
$ perl -pe 'BEGIN {$x="Line one to insert\nLine 2\nLine3\n"} $_=$x.$_ if /USA/ ' MeanwhileInHell.txt
Iran|XXXXXX|Iranian
Iraq|YYYYYY|Iraquian
Saudi|ZZZZZ|Saudi is a Rich Country
Line one to insert
Line 2
Line3
USA|AAAAAA|USA is United States of America.
India|IIII|India got freedom from British.
Scot|SSSSS|Canada Mexio.
$

Это может работать для вас (GNU sed & Bash):

sed -i $'/Line to insert after/a\line1\\nline2\\nline3' file
Другие вопросы по тегам