使用sed在第一次匹配后插入行

use*_*250 228 shell sed

出于某种原因,我似乎无法找到一个直截了当的答案,而且我现在有点紧张.在使用该sed命令匹配特定字符串的第一行之后,如何插入选择行文本.我有 ...

CLIENTSCRIPT="foo"
CLIENTFILE="bar"
Run Code Online (Sandbox Code Playgroud)

我想在行之后插入一行,CLIENTSCRIPT=导致......

CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
Run Code Online (Sandbox Code Playgroud)

Gil*_*not 357

尝试使用GNU sed执行此操作:

sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
Run Code Online (Sandbox Code Playgroud)

如果你想在原地替换,请使用

sed -i '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
Run Code Online (Sandbox Code Playgroud)

产量

CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
Run Code Online (Sandbox Code Playgroud)

文件

  • 注意,两者都假设GNU`sed`.这不是标准的`sed`语法,不适用于任何其他`sed`实现. (10认同)
  • 它如何仅适用于第一场比赛?很明显它在比赛结束后附加了文字,但它如何只知道第一场比赛? (9认同)
  • 对于我来说,这会在每场比赛后添加文字. (7认同)
  • 我很难让它为我工作,因为我使用了不同的分隔符。RTFM 后,我意识到我必须以 \ 开头正则表达式,然后是分隔符。 (3认同)

Ste*_*las 46

注意标准sed语法(如在POSIX中,因此所有符合sed实现的所有实现都支持(GNU,OS/X,BSD,Solaris ...)):

sed '/CLIENTSCRIPT=/a\
CLIENTSCRIPT2="hello"' file
Run Code Online (Sandbox Code Playgroud)

或者在一条线上:

sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
Run Code Online (Sandbox Code Playgroud)

(-expressions(以及iles的内容-f)与换行符一起组成sed脚本sed解释).

-i就地编辑的选项也是一个GNU扩展,其他一些实现(如FreeBSD)支持-i ''.

或者,为了便于携带,您可以使用perl:

perl -pi -e '$_ .= qq(CLIENTSCRIPT2="hello"\n) if /CLIENTSCRIPT=/' file
Run Code Online (Sandbox Code Playgroud)

或者您可以使用edex:

printf '%s\n' /CLIENTSCRIPT=/a 'CLIENTSCRIPT2="hello"' . w q | ex -s file
Run Code Online (Sandbox Code Playgroud)

  • 我可能是错的,但是当前的 `sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file` 转义了第一个参数末尾的引号并中断了命令。 (2认同)
  • 显然,MacOS 上的终端(以及随后在终端中运行的脚本)也是一个例外。我找到了替代语法,但无论如何还是谢谢。 (2认同)

SLe*_*ort 14

符合POSIX标准的s命令:

sed '/CLIENTSCRIPT="foo"/s/.*/&\
CLIENTSCRIPT2="hello"/' file
Run Code Online (Sandbox Code Playgroud)


Bre*_*zer 10

Sed命令适用于MacOS(至少OS 10)和Unix一样(即不需要像Gilles(目前接受)那样的gnu sed):

sed -e '/CLIENTSCRIPT="foo"/a\'$'\n''CLIENTSCRIPT2="hello"' file
Run Code Online (Sandbox Code Playgroud)

这适用于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
Run Code Online (Sandbox Code Playgroud)

(这会在行插入代码之后创建一个循环,它只循环遍历文件的其余部分,永远不会再次返回第一个sed命令).

您可能会注意到我在匹配模式中添加了"^*",以防该行显示在注释中,比如说或缩进.它不是100%完美,但涵盖了其他一些可能很常见的情况.根据需要调整......

这两个解决方案也解决了问题(对于添加线的通用解决方案),如果你的新插入行包含未转义的反斜杠或者&符号,它们将被sed解释,并且可能不会出现相同的情况,就像\n是 - 例如.\0将是匹配的第一行.特别方便的是,如果你要添加一个来自变量的行,你必须先使用$ {var //}之前必须先逃避所有内容,或者使用另一个sed语句等.

这个解决方案在脚本中不那么混乱(引用和\n不容易阅读),当你不想在行的开头放置a命令的替换文本时,如果在一个函数中带有缩进的线条.我已经利用shell将$'\n'评估为换行符,而不是常规'\n'单引号值.

虽然我认为perl /甚至awk可能会因为更具可读性而获胜,但它已经足够长了.


siw*_*sam 8

对此发布答案可能有点晚了,但我发现上述一些解决方案有点麻烦。

我在 sed 中尝试了简单的字符串替换,它起作用了:

sed 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file
Run Code Online (Sandbox Code Playgroud)

&符号反映匹配的字符串,然后添加 \n 和新行。

如前所述,如果您想就地进行:

sed -i 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file
Run Code Online (Sandbox Code Playgroud)

另一件事。您可以使用表达式进行匹配:

sed -i 's/CLIENTSCRIPT=.*/&\nCLIENTSCRIPT2="hello"/' file
Run Code Online (Sandbox Code Playgroud)

希望这有助于某人


Cor*_*ier 7

awk 变体:

awk '1;/CLIENTSCRIPT=/{print "CLIENTSCRIPT2=\"hello\""}' file
Run Code Online (Sandbox Code Playgroud)

  • 对于任何想知道“1;”的人,请参阅[为什么 awk 中的“1”打印当前行?](/sf/ask/1418400861/当前行) (2认同)