在文件中指定模式之前插入多行
如果内容中有新行,并且此内容由函数生成,则无法在匹配行之前添加行
另一个看起来不错的替代方案( 使用 shell 脚本在指定模式后将多行插入文件中 )但它只附加了“AFTER”。我需要“BEFORE”
然后将 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:未知命令:`<'
出现该错误很正常,您的文本语法与 sed 命令不兼容,请允许我详细说明:
-
首先,您的文本中有很多
/
,而/
是sed
中的分隔符,这会混淆命令,这就是您出现该错误的原因。因此,您应该将文本中的所有/
都转义,方法是将其替换为\\/
(额外的\
将由 shell 解释)。 -
其次,在
sed
的 man 中,我们可以看到关于/i
的这一小行:
Insert text, which has each embedded newline preceded by a backslash
这意味着您还需要在每个换行符前添加一个
\
,在您的示例中,这意味着在每个
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
使用
e
代替
r
。
来自 Sed 手册中有关
e
命令的内容:
Note that, unlike the r command, the output of the command will be printed immediately; the r command instead delays the output to the end of the current cycle.
r
命令的延迟是问题所在,您无法在它之后输出任何内容。
e
命令的示例:
seq 0 9 | sed -e '/4/{
h
e cat add.xml
g
}'
h
将匹配行复制到保留空间,而
g
将其复制回模式空间。这样,它就会出现在输出中的“add.xml”之后。
假设您只想在第一个
之前插入
/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
很丑陋,但它是必需的