首页 文章

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

提问于
浏览
195

出于某种原因,我现在可以在一段时间内处于紧张状态 . 如何使用 sed 命令在匹配特定字符串的第一行之后插入选择行文本 . 我有 ...

CLIENTSCRIPT="foo"
CLIENTFILE="bar"

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

CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"

7 回答

  • 12

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

    sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
    

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

    sed -i '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
    

    输出

    CLIENTSCRIPT="foo"
    CLIENTSCRIPT2="hello"
    CLIENTFILE="bar"
    

    Doc

    • sed doc并搜索 \a (追加)
  • 42

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

    sed '/CLIENTSCRIPT=/a\
    CLIENTSCRIPT2="hello"' file
    

    或者在一条线上:

    sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
    

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

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

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

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

    或者您可以使用 edex

    printf '%s\n' /CLIENTSCRIPT=/a 'CLIENTSCRIPT2="hello"' . w q | ex -s file
    
  • 316

    符合POSIX标准的使用 s 命令:

    sed '/CLIENTSCRIPT="foo"/s/.*/&\
    CLIENTSCRIPT2="hello"/' file
    
  • 0

    Sed命令适用于MacOS(至少OS 10)和Unix一样(即不需要像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命令的替换文本时,如果在一个函数中带有缩进的线条 . 我已经利用shell将$'\ n'评估为换行符,而不是常规'\ n'单引号值 .

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

  • 0

    我有类似的任务,并且无法使上述perl解决方案起作用 .

    这是我的解决方案:

    perl -i -pe "BEGIN{undef $/;} s/^\[mysqld\]$/[mysqld]\n\ncollation-server = utf8_unicode_ci\n/sgm" /etc/mysql/my.cnf

    Explanation:

    使用正则表达式在我的/etc/mysql/my.cnf文件中搜索仅包含 [mysqld] 的行,并将其替换为

    [mysqld] collation-server = utf8_unicode_ci

    在包含 [mysqld] 的行之后有效添加 collation-server = utf8_unicode_ci 行 .

  • 0

    我最近不得不处理这个,但不仅仅是一个文件,而是多个不同的文件,我不能手工完成 . 所以我必须为它找到一个脚本 .

    脚本下载:kinglazy-autoinsert.sh

    Usage:

    kinglazy-autoinsert.sh(list_file)(pattern_file)

    Explanation of parameters:

    list_file =这是包含要编辑的文件列表的绝对路径的文件

    pattern_file =这是您指定要在其下添加新文本的模式(在第一列中)的文件 . 要在模式下添加的新文本在第二列中指定 . 这就是它!

    该脚本可以节省时间并帮助您尽可能轻松地完成工作 .

    依赖性:无

  • 5

    也许为此发布一个答案有点晚了,但我发现上面的一些解决方案有点麻烦 .

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

    sed 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file
    

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

    如上所述,如果您想要就地执行此操作:

    sed -i 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file
    

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

    sed -i 's/CLIENTSCRIPT=.*/&\nCLIENTSCRIPT2="hello"/' file
    

    希望这有助于某人

相关问题