SED正则表达式从命令文本中查找(和删除)选项

时间:2017-02-23 17:19:30

标签: regex bash sed

我有一个包含param = option [,选项...]的配置文件,使用标准bash实用程序,也许是 sed 的帮助,删除一个选项从列表中。

     #
     param=aa,bb,cc
     param=aa,bb
     param=bb,cc
     param=bb
     #

在此示例中,我想从所有行中删除' bb' (以及分隔符),在最后一种情况下,因为' bb& #39; 是唯一的选择,删除完整的行,因此最终结果将是

     #
     param=aa,cc
     param=aa
     param=cc
     #

选项' bb' 可以单独使用,也可以在列表的开头,中间或末尾。显然,' bb'不应考虑嵌入另一个选项名称(即xxbb,bbxx等)。

编辑:修复拼写错误,添加' l示例

4 个答案:

答案 0 :(得分:2)

以下是sed版本,用于从任意位置移除bb参数,如果bb是唯一参数,则删除该行:

首先是输入文件:

#
param=aa,bb,cc
param=aa,bb
param=bb,cc
param=bb
#

现在运行此sed

sed -E '/^param=/{/=bb$/d; s/,bb(,|$)/\1/; s/=bb,/=/;}' file

这将给出:

#
param=aa,cc
param=aa
param=cc
#

要使用内联编辑,请使用:

sed -i.bak -E '/^param=/{/=bb$/d; s/,bb(,|$)/\1/; s/=bb,/=/;}' file

答案 1 :(得分:1)

注意:以下解决方案不解决更新输入文件;一种简单的(虽然不是完全健壮的)方法是使用
awk '...' file > file.$$ && mv file.$$ file

符合POSIX标准的awk解决方案应该可以有效运行:

awk -F'=' '
  $1 != "param" { print; next }
  {
    sub(/,bb,/, ",", $2)
    sub(/(^|,)bb$/, "", $2)
    if ($2 != "") print $1 FS $2
  }
' file

GNU awk允许使用其(非标准)gensub()函数提供更简单的解决方案:

awk -F'=' '
  $1 != "param" { print; next }
  {
    newList = gensub(/(^|,)bb(,|$)/, "\\2", 1, $2)
    if (newList != "") print $1 FS newList
  }
' file

符合POSIX标准的基于字段的替代方案(更详细,但可能更容易概括):

awk -F'=' '
  $1 != "param" { print; next }
  {
    n = split($2, opts, ","); optList = ""
    for (i=1; i<=n; ++i) {
      if (opts[i] != "bb") {
        optList = optList (optList == "" ? "" : ",") opts[i]
      }
    }
    if (optList != "") print $1 FS optList
  }
' file

答案 2 :(得分:0)

我使用临时格式来更容易地找到事件。要删除行,我建议使用grep

sed 's/=/=,/;s/$/,/;s/,bb,/,/;s/=,/=/;s/,$//;/=$/d'

s/=/=,/将其转换为:

param=,aa,bb,cc
param=,aa,bb
param=,bb

而不是s/$/,/

param=,aa,bb,cc,
param=,aa,bb,
param=,bb,

而不是s/,bb,/,/

param=,aa,cc,
param=,aa,
param=,

s/=,/=/;s/,$//将在开始时删除逗号并再次结束

删除空选项可以使用grep -v '=$'或更高级的sed魔法(因此它仍然可以与sed -i一起使用)

编辑: “sed magic”只是附加'/ = $ / d'

测试了这个,它运行正常:

sed -i 's/=/=,/;s/$/,/;s/,bb,/,/;s/=,/=/;s/,$//;/=$/d' filename

sed 's/=/=,/;s/$/,/;s/,bb,/,/;s/=,/=/;s/,$//;/=$/d' filename_in > filename_out

答案 3 :(得分:0)

假设你的Input_file如下:

param=aa,bb,cc
param=aa,bb
param=bb

然后是以下代码:

awk -F"=" '$2=="bb"{next} {sub(/,bb/,"");print}'  Input_file

输出:

param=aa,cc
param=aa