Добавить содержимое файла в другой файл только после первого совпадения - PullRequest
1 голос
/ 29 марта 2019

Используя bash, у меня есть эта строка кода, которая добавляет содержимое временного файла в другой файл после определенного соответствия:

sed -i "/text_to_match/r ${tmpFile}" ${fileName}

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

Я пытался использовать адреса:

sed -i "0,/text_to_match//text_to_match/r ${tmpFile}" ${fileName}

Но это не работает, говоря, что "/" - неизвестная команда.

Я могу заставить адреса работать, если я использую стандартную замену "s / to_replace / with_this /", но я не могу заставить ее работать с этой командой sed. Кажется, я не могу использовать адреса, если моя команда sed начинается с / вместо буквы.

Я не застрял с адресами, если я могу вставить содержимое временного файла в другой файл только один раз.

Ответы [ 4 ]

3 голосов
/ 29 марта 2019

Вы получаете эту ошибку, потому что если у вас есть диапазон адресов (ADDR1, ADDR2), вы не можете поставить другой адрес после него: sed ожидает команду там, а / не является командой.

Вы можете использовать здесь несколько скобок:

$ seq 20 > file
$ echo "new content" > tmpFile
$ sed '0,/5/{/5/ r tmpFile
}' file

выводит новый текст только после первой строки с 5

1
2
3
4
5
new content
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Я обнаружил, что мне нужно поставить новую строку после имени файла. Я получаю эту ошибку в противном случае

sed: -e expression #1, char 0: unmatched `{'

Похоже, что sed принимает всю оставшуюся строку в качестве имени файла.

Наверное, лучше написать

sed '0,/5/ {
    /5/ r tmpFile 
}' file

Полная прозрачность: я не использую sed, за исключением очень простых задач. На самом деле я бы использовал awk для этой работы

awk '
    {print} 
    !seen && $0 ~ patt {
        while (getline line < f) print line
        close(f)
        seen = 1
    }
'  patt="5" f=tmpFile file
2 голосов
/ 29 марта 2019

Гленн Джекман дал отличный ответ, почему попытка ОП не сработала.

В продолжение ответа Гленна Джекмана, если вы хотите, чтобы команда была в одной строке, вы должны использовать ветвление, чтобы команда r была в конце.

За командами редактирования, отличными от {...}, a, b, c, i, r, t, w, : и #, может следовать , необязательные символы и другая команда редактирования.Однако, когда команда редактирования s используется с флагом w, выполнение этой команды другой командой таким образом приводит к неопределенным результатам. [source: POSIX sed Standard ]

Команды r,R,w,W анализируют имя файла до конца строки.Если пробелы, комментарии или точки с запятой найдены, они будут включены в имя файла, что приведет к неожиданным результатам. [источник: Руководство по GNU sed ]

, что дает:

sed -e '1,/pattern/{/pattern/ba};b;:a;r rfile' file
1 голос
/ 29 марта 2019

GNU sed также позволяет s///e раскошелиться. Итак, есть одна строка, использующая tmpFile и файл Гленна.

sed '0,/5/{//{p;s/.*/cat tmpFile/e}}' file

  • // для повторения предыдущего совпадения паттерна (помогает, если оно длиннее /5/)
  • p для печати соответствующей строки
  • s/.*/cat tmpFile/e, чтобы очистить буфер шаблонов и вставить туда команду оболочки cat tmpFile, e выполнить ее и вывести вывод в поток
0 голосов
/ 29 марта 2019

У вас есть две косые черты вместе, прямо рядом друг с другом во втором примере sed.

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