Вставить несколько строк в файл перед указанным шаблоном - PullRequest
3 голосов
/ 07 июня 2019

Невозможно добавить строки перед совпадающей строкой, если у контента есть новые строки, и этот контент генерируется функцией

еще одна хорошая альтернатива ( Вставка нескольких строк в файл после указанного шаблона, используясценарий оболочки ), но он добавляет только «ПОСЛЕ».Мне нужно "ДО"

поместить содержимое XML в add.txt, а затем

sed '/ 4 / r add.txt' $ FILE

#/bin/sh

FILE=/tmp/sample.txt
form_xml_string()
{
  echo "<number value=\"11942\">"
  echo "  <string-attribute>\"hello\"</string-attribute>"
  echo "</number>"
}

create_file()
{
  if [ -e $FILE ]
  then
          echo "Removing file $FILE"
          rm $FILE
  fi

  i=1
  while [ $i -le 5 ]
  do
          echo "$i" >> $FILE
          i=$(( i+1 ))
   done
}

create_file
cat $FILE

# file sample.txt has numbers 1 to 5 in each line
# Now append the content from form_xml_string to line before 4
# command I tried
CONTENT=`form_xml_string`
echo "CONTENT is $CONTENT"
sed -i "/4/i $CONTENT" $FILE
cat $FILE

Ожидаемый результат:

1
2
3
<number value="11942">
  <string-attribute>"hello"</string-attribute>
</number>
4
5

Фактический вывод (или ошибка): sed: -e выражение # 1, символ 31: неизвестная команда: `<'</p>

Ответы [ 2 ]

3 голосов
/ 07 июня 2019

Это нормально, что вы получаете эту ошибку, синтаксис вашего текста не совместим с вашей командой sed, позвольте мне уточнить:

  • Во-первых, у вас много / s в вашем тексте, а / - это разделитель в sed, который запутывает команду, поэтому вы получаете эту ошибку.Таким образом, вы должны экранировать все / в тексте, который вы используете, заменив их на \\/ (дополнительный \ будет интерпретироваться оболочкой).

  • Во-вторых, в человеке для sed мы можем видеть эту маленькую строку около /i:

Вставить текст, в котором каждой встроенной новой строке предшествует обратная косая черта

Это означает, что вам также нужно добавить \ перед каждой новой строкой, в вашем примере это означает добавление \\ в конце каждого echo.

Редактировать:

Благодаря комментарию Toby Speight я заметил, что совершенно забыл о возможности изменения разделителя sed, который может сделать вашу жизнь многопроще, поскольку вам не нужно будет добавлять \\ перед каждым / в вашем тексте.Для этого все, что вам нужно, это изменить эту строку sed -i "/4/i $CONTENT" $FILE, например, на sed -i "\\_4_i $CONTENT" $FILE.

. Вот как будет выглядеть ваш сценарий после внесения этих изменений:

#! /bin/sh
FILE=/tmp/sample.txt
form_xml_string()
{
  echo "<number value=\"11942\">\\"
  echo "  <string-attribute>\"hello\"</string-attribute>\\"
  echo "</number>"
}

create_file()
{
  if [ -e $FILE ]
  then
          echo "Removing file $FILE"
          rm $FILE
  fi

  i=1
  while [ $i -le 5 ]
  do
          echo "$i" >> $FILE
          i=$(( i+1 ))
   done
}

create_file
cat $FILE

# file sample.txt has numbers 1 to 5 in each line
# Now append the content from form_xml_string to line before 4
# command I tried
CONTENT=`form_xml_string`
echo "CONTENT is $CONTENT"
sed -i "\\_4_i $CONTENT" $FILE
cat $FILE
1 голос
/ 07 июня 2019

Используйте e вместо r.

Из руководства Sed о команде e:

Обратите внимание, что в отличие от команды r, выводкоманда будет напечатана немедленно;Команда r вместо этого задерживает вывод до конца текущего цикла.

Задержка команды r является проблемой, из-за которой вы ничего не можете вывести после нее.

Пример команды e:

seq 0 9 | sed -e '/4/{
  h
  e cat add.xml
  g
}'

h копирует совпадающую строку в пространство удержания, а g копирует ее обратно в пространство образца.Этим он появляется после «add.xml» в выводе.

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