Answers:
尝试使用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
实现一起使用。
请注意标准sed
语法(与POSIX中一样,因此受所有符合的sed
实现(GNU,OS / X,BSD,Solaris ...)支持):
sed '/CLIENTSCRIPT=/a\
CLIENTSCRIPT2="hello"' file
或一行:
sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
(-e
xpression(和ile的内容-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
在第一个参数末尾转义了引号并中断了命令。
csh
或rc
家族)的外壳中,@ AbandonedCart '...'
是强引号,里面的反斜杠并不特殊。我知道的唯一例外是fish
外壳。
sed
不兼容POSIX 的macOS 。这使我对其可移植性的陈述不正确(对于单行变体)。我会请opengroup确认是否确实不符合标准或对我的标准有误解。
POSIX兼容的,使用以下s
命令:
sed '/CLIENTSCRIPT="foo"/s/.*/&\
CLIENTSCRIPT2="hello"/' file
sed -e '/.../s/$/\' -e 'CLI.../'
这将避免包含字节序列的行不构成有效字符的问题。
可以在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语句等先对所有内容进行转义。
如果您不想将a命令的替换文本放在一行的开头(例如,在函数中),则此解决方案在脚本中的混乱程度会降低(尽管引号和\ n并不容易阅读)缩进线。我利用了$'\ n'由shell评估为换行符的优点,而不是用常规的'\ n'单引号引起来。
尽管它足够长,但我认为perl / even awk可能会因更具可读性而获胜。
s/CLIENTSCRIPT="foo"/&\
[Enter] CLIENTSCRIPT2="hello"/
。反斜杠必须是该行的最后一个字符(其后没有空格),这与该注释中的样子相反。
s///
以及a
和i
命令中的@tatsu换行符。
对此发布答案可能有点晚,但是我发现上述解决方案有些繁琐。
我在sed中尝试了简单的字符串替换,它的工作原理是:
sed '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或者你已经安装了GNU莫名其妙的sed除非MacOS的工作。使用香草sed,您可以通过“转义”换行符来嵌入换行符,即以反斜杠结束该行,然后按[Enter](在标题下的参考,[2addr]s/BRE/replacement/flags
)。这意味着您的sed命令必须在终端中跨越多行。
awk变体:
awk '1;/CLIENTSCRIPT=/{print "CLIENTSCRIPT2=\"hello\""}' file
1;
,请参见为什么awk中的“ 1”会打印当前行?
我有类似的任务,但无法使上述perl解决方案正常工作。
这是我的解决方案:
perl -i -pe "BEGIN{undef $/;} s/^\[mysqld\]$/[mysqld]\n\ncollation-server = utf8_unicode_ci\n/sgm" /etc/mysql/my.cnf
说明:
使用正则表达式在我的/etc/mysql/my.cnf文件中搜索仅包含[mysqld]
并替换为的行
[mysqld]
collation-server = utf8_unicode_ci
有效地collation-server = utf8_unicode_ci
在包含的行之后添加行[mysqld]
。
我最近在Mac和Linux OS上也都必须这样做,在浏览了许多文章并尝试了许多方法之后,我特别认为我从来没有想过要去的地方:使用已知的方法足以理解解决方案以及带有简单模式的标准命令,一根衬垫,可移植,可扩展以增加更多约束。然后,我尝试以不同的角度来看待它,那时候我意识到,如果“ 2-衬里”满足我的其他标准,我可以不用“一个衬里”选项。最后,我想出了这个解决方案,我希望它可以在Ubuntu和Mac上使用,我想与大家分享:
insertLine=$(( $(grep -n "foo" sample.txt | cut -f1 -d: | head -1) + 1 ))
sed -i -e "$insertLine"' i\'$'\n''bar'$'\n' sample.txt
在第一个命令中,grep查找包含“ foo”的行号,cut / head选择第一个出现的行,并且由于我想在出现后插入,算术op将第一个出现的行号加1。在第二个命令中,它是就地文件编辑,用于插入“ i”:用ansi-c引用新行,“ bar”,然后是另一行。结果是在“ foo”行之后添加了一个包含“ bar”的新行。这两个命令中的每一个都可以扩展为更复杂的操作和匹配。