【问题标题】:How can I delete a string inside parentheses using sed, inside a sed script?如何在 sed 脚本中使用 sed 删除括号内的字符串?
【发布时间】:2021-12-12 18:21:58
【问题描述】:

我想在 sed 脚本中使用 sed 删除括号内的文本(包括括号)。例如,我想删除短语 (Chris Pratt) 和 (Chris-Pratt) 并保留 (Chris_Pratt)。 (他们都在同一条线上)。并对整个文件执行此操作。例如,该行如下所示:

Star Lord (Chris Pratt), (Chris-Pratt), age 42, actor, (Chris_Pratt)

这是我希望在 sed 脚本中执行 sed 命令后的样子:

Star Lord, age 42, actor, (Chris_Pratt)

这就是我想要对每一行执行的操作(有多行具有其他名称)。

我已经试过了:

s/[(][^)]*[)]//g

这个可行,但它也删除了括号包括下划线,还有:

s/\([[:alpha:]]{1,} [[:alpha:] ]{1,}\)\ //g

当我在命令行中正常使用 sed 运行它时,它确实有效,但由于某种原因在脚本中运行它时它不起作用。

【问题讨论】:

    标签: bash ubuntu sed


    【解决方案1】:

    你可以使用

    sed 's/ *([^()_]*)//g' file > outputfile
    

    与 POSIX ERE 语法相同的模式:

    sed -E 's/ *\([^()_]*\)//g' file > outputfile
    

    详情

    • *
    • ( - 文字 ( 字符(因为它是 POSIX BRE 模式),当使用 POSIX ERE 时,必须使用 \(
    • [^()_]* - 除了()_ 之外的零个或多个字符
    • ) - 文字 ) 字符(因为它是 POSIX BRE 模式),当使用 POSIX ERE 时,必须使用 \)

    online demo

    #!/bin/bash
    s='Star Lord (Chris Pratt), age 42, actor, (Chris_Pratt)'
    sed 's/ *([^()_]*)//g' <<< "$s"
    # => Star Lord, age 42, actor, (Chris_Pratt)
    sed -E 's/ *\([^()_]*\)//g' <<< "$s"
    # => Star Lord, age 42, actor, (Chris_Pratt)
    

    演示截图:

    【讨论】:

    • 嗯。当我运行这个命令时,它会删除我文件中的所有文本,只留下括号和下划线。不确定发生了什么?
    • @JoshuaBorden 你没有使用我的代码。
    • 我确实在使用确切的代码。你在说什么?
    • @JoshuaBorden 如果您使用sed 's/ *([^()_]*)//g' file &gt; outputfileoutputfile 将具有预期的文本。
    • @JoshuaBorden 那么,它现在是否适用于 POSIX ERE 模式?您必须有-r-E 选项。
    【解决方案2】:

    第一个解决方案(sed 解决方案): 使用您展示的示例,请尝试遵循sed 程序。在此处使用sed 的反向引用功能。

    sed -E 's/(^[^(]*) \([^)]*\), \([^)]*\)(.*)/\1\2/' Input_file
    

    解释:在这里使用sed-E 选项在我们的程序中启用ERE(扩展正则表达式)。然后在主程序中使用seds 选项进行替换操作。我们提到了(^[^(]*) \([^)]*\), \([^)]*\)(.*),它在这里创建了 2 个反向引用(内存中的一个临时空间,用于稍后在程序中检索捕获的值)。同时使用\1(第一个反向引用)和\2(第二个反向引用)来获得OP提到的预期输出。

    正则表达式的解释:

    (^[^(]*)               ##Creating 1st capturing group which captures values from starting of line to till 1st occurrence of ( here.
     \([^)]*\), \([^)]*\)  ##Matching space ( till next occurrence of ) here followed by comma then space followed by ( till next occurrence of ).
    (.*)                   ##Creating 2nd capturing group which has everything after previous match.
    


    第二个解决方案(awk 解决方案): 在这里添加了一个awk 解决方案,使用awkmatch 函数。使用的正则表达式与上面提到的相同,因此对该程序的简单解释是;通过此功能匹配不需要的部分并仅打印需要的部分。

    awk '
    match($0,/[[:space:]]*\([^)]*\),[[:space:]]*\([^)]*\)/){
      print substr($0,1,RSTART-1) substr($0,RSTART+RLENGTH)
    }
    ' Input_file
    

    【讨论】:

    • 很抱歉我忘了提这个!还有一个带有“-”的括号,就像这样“(Earth-16)”我也需要摆脱它。您的代码完美运行。有没有办法删除那个也有“-”的?
    • @JoshuaBorden,肯定不是问题,请尝试以下代码:sed -E 's/(^[^(]*) \([^)]*\), \([^)]*\)(.*)/\1\2/' Input_file 一次,然后告诉我进展如何,干杯。
    【解决方案3】:

    这可能对你有用(GNU sed):

    sed -E ':a;s/ *\([^()]*\),(.*\(.*\))/\n\1/;ta;s/,*\n+/,/g' file
    

    用换行符替换括号中的所有文字(包括括号),前面有一个可能的空格,后面是,,后面至少还有一个括号内的文字。

    然后用单个, 替换前面可能有, 的多个换行符。

    【讨论】:

      【解决方案4】:

      使用sed

      $ sed 's/,\? ([^)][A-Za-z -]*)//g' input_file
      Star Lord, age 42, actor, (Chris_Pratt)
      

      【讨论】:

        【解决方案5】:

        您应该澄清您是否真的在为“扩展”正则表达式使用-E选项。

        启用-E 后,括号 (()) 必须转义 (\() 以匹配字面意思。没有转义,它们被解释为组/字段分隔符(没有-E,这是相反的)。

        我的解决方案假设 -E 已开启。

        • 对于一个可执行的sed 脚​​本,你的shebang 应该类似于#!/bin/sed -Ef#!/usr/bin/env -Ssed -Ef

        • 对于不可执行的sed 脚本,像这样调用它:sed -Ef my-script

        解决方案:

        如果所有行都具有相同的布局,请使用:

        s/([[:space:]]+\([^)]+\),){2}/,/
        

        如果布局不同,请尝试以下:

        s/[[:space:]]*\([^)]*[- ][^)]+\)//
        s/[[:space:]]*\([^)]*[- ][^)]+\),?//g
        

        所有带括号的字段包含一个空格和/或破折号被删除,还有前导空格和尾随逗号(如果存在)。仅对于第一个匹配项,所有逗号都会保留。

        s/[[:space:]]*\([^)_]+\)//
        s/[[:space:]]*\([^)_]+\),?//g
        

        所有包含下划线的括号字段都将被删除(包括(Madonna))。用空格和逗号同上(如上)。

        编辑:我稍微误读了您的预期输出。你会得到Star Lord age 42, actor, (Chris_Pratt) 而不是Star Lord, age 42, actor, (Chris_Pratt)(注意第一个逗号)。我相应地修复了解决方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-19
          • 2019-08-24
          • 2017-05-28
          • 2011-12-12
          • 2010-12-23
          • 1970-01-01
          相关资源
          最近更新 更多