在文件中的指定模式之前插入多行

时间:2019-06-07 08:45:11

标签: bash shell sed

如果内容包含新行且此内容是由函数生成的,则无法在匹配行之前添加行

另一个看起来不错的替代方法(Insert multiple lines into a file after specified pattern using shell script),但仅附加了“ AFTER”。我需要“之前”

然后将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:未知命令:`<'

2 个答案:

答案 0 :(得分:3)

您通常会收到该错误,文本的语法与您的sed命令不兼容,请允许我详细说明:

  • 首先,您的文本中有很多/,而/sed中的定界符,这使命令感到困惑,这就是为什么要这样做的原因错误。因此,应将您使用的文本中的所有/都替换为\\/(多余的\将由shell解释)。

  • 第二,在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 :(得分:1)

使用e代替r

有关e命令的Sed手册:

  

请注意,与r命令不同,该命令的输出将立即打印;而是使用r命令将输出延迟到当前周期的末尾。

r命令的延迟是问题所在,您不能在其后输出任何内容。

e命令的示例:

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

h将匹配行复制到保留空间,g将其复制回到模式空间。这样,它就会出现在输出中的“ add.xml”之后。