由于某些原因,我似乎找不到一个简单明了的答案,而我现在时间比较紧迫。如何使用sed
命令在找到第一个与特定字符串匹配的行后插入一行选择文本。我有...
CLIENTSCRIPT="foo"
CLIENTFILE="bar"
我希望您在CLIENTSCRIPT=
行后插入一行,从而得到...
CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
由于某些原因,我似乎找不到一个简单明了的答案,而我现在时间比较紧迫。如何使用sed
命令在找到第一个与特定字符串匹配的行后插入一行选择文本。我有...
CLIENTSCRIPT="foo"
CLIENTFILE="bar"
我希望您在CLIENTSCRIPT=
行后插入一行,从而得到...
CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
尝试使用 GNU sed 进行此操作:
sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
如果您想进行原地替换,请使用
sed -i '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
\a
(追加)sed
。这不是标准的sed
语法,并且不适用于任何其他sed
实现。 - Stephane Chazelas请注意标准的sed
语法(如POSIX所述,因此受所有符合条件的sed
实现支持(包括GNU、OS / X、BSD、Solaris等)):
sed '/CLIENTSCRIPT=/a\
CLIENTSCRIPT2="hello"' file
或者在一行上:
sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
(-e
表达式(以及-f
文件的内容)将连接成一个字符串,每行末尾加上换行符,作为sed脚本提供给sed
解释执行。)
-i
选项用于原地编辑也是GNU扩展,一些其他实现(如FreeBSD)支持-i''
来实现同样功能。
或者,为了可移植性,您可以使用perl
代替:
perl -pi -e '$_ .= qq(CLIENTSCRIPT2="hello"\n) if /CLIENTSCRIPT=/' file
或者你可以使用 ed
或 ex
:
printf '%s\n' /CLIENTSCRIPT=/a 'CLIENTSCRIPT2="hello"' . w q | ex -s file
sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
转义了第一个参数结尾处的引号并破坏了命令。 - Abandoned Cartcsh
或 rc
家族的 shell 中,'...'
是强引用,其中反斜杠不是特殊字符。我所知道的唯一例外是 fish
shell。 - Stephane Chazelassed
不符合POSIX标准。这使得我对其可移植性的说法是不正确的(对于单行变体)。如果它确实是非一致性或者是我的标准误解,我会向opengroup询问确认。 - Stephane Chazelasprintf...ex
版本。这个版本非常好用! - Matthias Bohlen适用于MacOS(至少是OS 10)和Unix的Sed命令(即不像Gilles'(当前被接受的)那样需要gnu sed):
sed -e '/CLIENTSCRIPT="foo"/a\'$'\n''CLIENTSCRIPT2="hello"' file
这适用于bash和其他支持$'\n'评估引号样式的shell。一切都可以在一行中完成,并且适用于旧的/POSIX sed命令。如果可能会有多行匹配CLIENTSCRIPT="foo"(或类似的内容),并且您希望仅在第一次添加额外行,则可以按如下方式重新制作:
sed -e '/^ *CLIENTSCRIPT="foo"/b ins' -e b -e ':ins' -e 'a\'$'\n''CLIENTSCRIPT2="hello"' -e ': done' -e 'n;b done' file
(这在插入代码后创建了一个循环,使其只循环遍历文件的其余部分,永远无法回到第一个sed命令)。
您可能会注意到,在匹配模式中加入了'^ *',以防该行出现在注释中或缩进。虽然不是100%完美,但涵盖了一些其他常见情况。根据需要进行调整...
这两个解决方案也解决了(对于添加行的通用解决方案)的问题,即如果新插入的行包含未转义的反斜杠或和号,则它们将被sed解释,并且很可能不能相同,就像\n
一样-例如,\0
将是第一行匹配。特别适用于添加来自变量的行的情况,在这种情况下,您否则必须使用${var//}先转义所有内容,或者使用另一个sed语句等。
这个解决方案在脚本中有点混乱(那里的引用和 \n 很难读),当您不想在起始行上放置执行a命令的替换文本时,比如说在具有缩进行的函数中。我利用了$'\n'被shell评估为换行符的优势,而不是常规的'\n'单引号值。
虽然已经足够长了,但我认为perl / awk可能会因为更易读而获胜。
**[Enter]**
CLIENTSCRIPT2="hello"/`。反斜杠必须是该行的最后一个字符(不能在其后面有空格),与其在此注释中的外观相反。 - TheDudeAbidess///
替换字符串中的换行符,以及 a
和 i
命令中的换行符可以使用我在上面评论中描述的相同方法进行“转义”。 - TheDudeAbidess
命令的实现:sed '/CLIENTSCRIPT="foo"/s/.*/&\
CLIENTSCRIPT2="hello"/' file
sed -e '/.../s/$/\' -e 'CLI.../'
,这将避免包含无效字符字节序列的行出现问题。 - Stephane Chazelassed 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file
&符号反映了匹配的字符串,然后添加\n和新行。
如前所述,如果想要原地执行:
sed -i 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file
另外一件事。你可以使用一个表达式进行匹配:
sed -i 's/CLIENTSCRIPT=.*/&\nCLIENTSCRIPT2="hello"/' file
希望这能帮助到某人。
\n
。然而,普通的(POSIX)sed
不理解替换字符串中的\n
,所以在BSD或macOS上无法工作——除非你已经安装了GNU sed。使用普通的sed,您可以通过“转义”来嵌入换行符——也就是说,在行末加上反斜杠,然后按**[Enter]**键(参考,在[2addr]s/BRE/replacement/flags
标题下)。这意味着您的sed命令必须跨越终端的多行。 - TheDudeAbidesawk '1;/CLIENTSCRIPT=/{print "CLIENTSCRIPT2=\"hello\""}' file
insertLine=$(( $(grep -n "foo" sample.txt | cut -f1 -d: | head -1) + 1 ))
sed -i -e "$insertLine"' i\'$'\n''bar'$'\n' sample.txt