Объединение текстовых файлов, НО Вставка текста между ними

сед

В sed нет простого способа сделать то, что вы просите.
Самое простое переносимое POSIXly-решение для sed — что-то вроде:

sed -ne '/HI/{:1' -e 'n;p;b1' -e '}'

Другими простыми решениями являются:

sed '0,/HI/d'     ./file             # GNU sed
awk 'f; /HI/{f=1}'./file

изд

Ближайшее решение POSIXly non -sed — это ed. Просто удалите диапазон от первой строки файла до регулярного выражения /HI/, даже если HIнаходится в той же первой строке.

printf '%s\n' 1,/HI/d,p Q | ed -s file

Или

ed -Gs imfile2 <<-\edscript
1,/HI/d
,p
Q
edscript

Что означает:

  • печать без дополнительной информации (количество прочитанных строк )с опцией-s
  • удалить (удалить )все строки от первой строки fileдо регулярного выражения/HI/(1,/HI/d).
  • , затем распечатайте весь файл (,p).
  • и выйти, даже если файл был изменен(Q).

Если вы хотите изменить файл, замените ,p Qпростоw(и запишите в файл ).

Почему sedне работает на 1,/HI/d, а edработает?

Потому что sedожидает совпадения регулярного выражения на следующей строке.

В edлибо 3,33,/3//3/,3/3/,/3/, либо3,33,/3//3/,3/3/,/3/будет напечатано только одно 3:

$ printf '%s\n' 3,3p   3,/3/p   /3/3p   /3/,/3/p   Q | ed -s <(seq 5)
3
3
3
3

Пока этим занимается sed:

$ sed -ne 3,3p  <(seq 5)
3

$ sed -ne 3,/3/p  <(seq 5)
3
4
5

$ sed -ne /3/,3p  <(seq 5)
3

$ sed -ne /3/,/3/p <(seq 5)
3
4
5

Ожидается, что регулярное выражение в конце диапазона будет соответствовать строке , следующей за строкой, соответствующей началу диапазона (слева от,). Нет 3следующей за строкой с номером 3, поэтому sed печатает все следующие строки(4и5).

Вот почему GNU sed решает проблему с помощью 0,/HI/.

Почему :1;n;p;b1?

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

$     sed -n '5{:1;n;p;b1}' <(seq 8)    # GNU syntax
6
7
8

Итак, просто сопоставьте нужное регулярное выражение /HI/и войдите в такой цикл.

sed -n '/HI/{:1;n;p;b1}' file        # GNU syntax

Который необходимо расширить до более сложного сценария, потому что некоторые старые sed не позволяют завершить labelsс помощью ;.

sed -n -e '/HI/{:1' -e 'n;p;b1' -e '}' file        # portable syntax
0
12.10.2021, 19:33
1 ответ

Метод с использованием встроенных функций оболочки set, shiftи printfбез цикла:

echo " \'id#\',\',name,\' " > /tmp/foo
set -- test_file[0-9]*
f="$1"
shift
cat "$1" $(printf '/tmp/foo %s ' "$@")
rm /tmp/foo    
0
14.10.2021, 18:03

Теги

Похожие вопросы