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

问题描述 投票:0回答:3

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

另一个看起来不错的替代方案(使用 shell 脚本在指定模式之后将多行插入到文件中),但它只附加“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:未知命令:`<'

bash shell sed
3个回答
4
投票

出现该错误是正常的,您的文本语法与 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

2
投票

使用

e
代替
r

来自 Sed 手册中关于

e
命令的信息:

注意,与r命令不同,该命令的输出将立即打印; r 命令将输出延迟到当前周期结束。

r
命令的延迟是问题所在,在它之后你无法输出任何内容。

e
命令示例:

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

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


0
投票

假设您只想在第一个

/tmp/snippet
之前插入
}
的内容。

awk '
    /}/ && !done {          # Search for the first "}" and check if insertion is not done
        while ((getline line < "/tmp/snippet") > 0) {
            print line      # Print each line from the snippet file
        }
        print "}"           # Print the original "}" after the snippet
        done=1              # Set done to 1 to avoid further insertions
        next                # Skip the original line containing "}"
    }
    { print }               # Print all other lines as is
' /path/to/file > /tmp/tmp2 && mv /tmp/tmp2 /path/to/file

必须拥有

/tmp/tmp2
很难看,但这是必需的

© www.soinside.com 2019 - 2024. All rights reserved.