我有一个包含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示例
答案 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