【问题标题】:How to use sed command to add a string before a pattern string?如何使用 sed 命令在模式字符串之前添加一个字符串?
【发布时间】:2011-07-08 04:16:51
【问题描述】:

我想使用 sed 修改我的名为“baz”的文件。

当我搜索模式 foo 时,foo 不在行首或行尾,我想在 foo 之前附加 bar,我该如何使用 sed?

Input file named baz:
blah_foo_blahblahblah
blah_foo_blahblahblah
blah_foo_blahblahblah
blah_foo_blahblahblah

Output file 
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah

【问题讨论】:

    标签: bash sed


    【解决方案1】:

    你可以使用类似的东西:

    sed 's/foo/barfoo/g' baz
    

    (末尾的g 表示全局,每行的每一次出现,而不仅仅是第一次出现)。

    对于 任意(而非固定)模式,例如 foo[0-9],您可以使用如下捕获组:

    pax$ echo 'xyz fooA abc
    xyz foo5 abc
    xyz fooB abc' | sed 's/\(foo[0-9]\)/bar\1/g'
    
    xyz fooA abc
    xyz barfoo5 abc
    xyz fooB abc
    

    括号捕获与模式匹配的实际文本,\1 在替换中使用它。

    您可以在此模式中使用任意复杂的模式,包括确保只匹配完整的单词。例如,仅当它立即被单词边界包围时才更改模式:

    pax$ echo 'xyz fooA abc
    xyz foo5 abc foo77 qqq xfoo4 zzz
    xyz fooB abc' | sed 's/\(\bfoo[0-9]\b\)/bar\1/g'
    
    xyz fooA abc
    xyz barfoo5 abc foo77 qqq xfoo4 zzz
    xyz fooB abc
    

    就捕获组的工作方式而言,您可以使用括号来存储与模式匹配的文本,以便以后在替换中使用。捕获的标识符基于从左到右读取的 ( 字符,因此是正则表达式(为了清楚起见,我省略了 \ 转义字符并稍微填充了它):

    ( ( \S* )   ( \S* ) )
    ^ ^     ^   ^     ^ ^
    | |     |   |     | |
    | +--2--+   +--3--+ |
    +---------1---------+
    

    当应用于文本 Pax Diablo 时,会为您提供三个组:

    \1 = Pax Diablo
    \2 = Pax
    \3 = Diablo
    

    如下图:

    pax$ echo 'Pax Diablo' | sed 's/\(\(\S*\) \(\S*\)\)/[\1] [\2] [\3]/'
    [Pax Diablo] [Pax] [Diablo]
    

    【讨论】:

    • 实际上我想在匹配模式之前附加一个字符串,有没有办法做到这一点?
    • 甚至sed 's/^foo/bar&/'
    • 嗯,foo 没有出现在行首或行尾
    • @Kit,在增加复杂性方面,我添加了一些其他选项。适应性最强的可能是最后一个,带有捕获组。
    • man 页面并不总是那么全面。您最好获取死树描述(书)或使用info sed 获取更多详细信息。我还会用更多的肉来更新我的答案。
    【解决方案2】:

    只需替换换行符的开头即可。

    sed '/^foo/s/^/bar/'
    

    【讨论】:

    • “s”是在匹配模式前加字符串吗?
    • 没有。这是用替换替换模式。该模式恰好是该行的开头。
    • foo不是行首怎么办?
    • 这就是搜索模式。 s 运算符在其后指定其操作数。
    【解决方案3】:

    要替换或修改除行首或行尾之外的所有“foo”,我建议在行首和行尾临时用唯一的标记值替换它们。

    sed 's/^foo/____veryunlikelytoken_bol____/
      s/foo$/____veryunlikelytoken_eol____/
      s/foo/bar&/g
      s/^____veryunlikelytoken_bol____/foo/
      s/____veryunlikelytoken_eol____$/foo/'
    

    sed 中无法指定“此处无法匹配”。在 Perl 正则表达式和派生词(意思是从 Perl 的正则表达式中借用的语言,不一定是从 Perl 派生的语言)中,您有各种否定断言,因此您可以执行类似的操作

    perl -pe 's/(?!^)foo(?!$)/barfoo/g'
    

    【讨论】:

      猜你喜欢
      • 2013-03-09
      • 1970-01-01
      • 2020-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多