SED 删除评论但保留特定的否定评论字符串

SED delete comments but leave specific negated comment strings

我正在尝试从文件中删除评论,但重要的是我想保留特定的字符串:

## Something
# START
# END

这些必须保留在 rest 未注释的行中,我想用 "d" 删除 rest - 这很重要。我不想使用打印否定或其他技巧,因为这个 sed 命令稍后还会使用附加的“-e”处理其他事情。

这是示例文件:

# START
group1: user1@domain.com, user2@domain.com, user3@domain.com
group2: user3@domain.com, user4@domain.com

# S
#STAR
# start
# star
# comment is here
## Owner1
group3: user1@domain.com, user3@domain.com

## Owner2
group4: user4@domain.com, user3@domain.com

group3: user2@domain.com, user3@domain.com

# END

group5: user4@domain.com
alias1: user6@domain.com

我尝试使用如下命令:

sed -e '/^#[^#]/d' sample.file

删除以“#”开头且下一个字符不是“#”的每一行,因此它会留下“##”行,但是如何在不丢失#START 和#END 行的情况下管理删除其余部分?

我需要在没有管道、“!p”或 "p" 版本的相同命令中执行此操作,它必须是这个 "d" 修改版本。 尝试过类似的东西:

sed -e '/^#[^#][^S][^T][^A][^R][^T]/d'

sed -e '/^#[^#]\([^S][^T][^A][^R][^T]\|[^E][^N][^D]\)/d'

但没有任何东西按我想要的方式工作。 我不确定这种方式是否可行。

预期输出:

# START
group1: user1@domain.com, user2@domain.com, user3@domain.com
group2: user3@domain.com, user4@domain.com

## Owner1
group3: user1@domain.com, user3@domain.com

## Owner2
group4: user4@domain.com, user3@domain.com

group3: user2@domain.com, user3@domain.com

# END

group5: user4@domain.com
alias1: user6@domain.com

问候并感谢您的帮助:)

尝试:

sed -E '/^##|^# START|^# END/bskip; /^#/d; :skip' file

示例

$ sed -E '/^##|^# START|^# END/bskip; /^#/d; :skip' file
# START
group1: user1@domain.com, user2@domain.com, user3@domain.com
group2: user3@domain.com, user4@domain.com

## Owner1
group3: user1@domain.com, user3@domain.com

## Owner2
group4: user4@domain.com, user3@domain.com

group3: user2@domain.com, user3@domain.com

# END

group5: user4@domain.com
alias1: user6@domain.com

工作原理

  • /^##|^# START|^# END/bskip

    对于匹配 ^##^# START^# END 的任何行,我们分支到标签 skip.

  • /^#/d

    对于所有其他以 # 开头的行,我们删除。

  • :skip

    这定义了标签skip.

BSD/macOS

以上是使用 GNU sed 测试的。对于 BSD/macOS sed,尝试:

sed -E -e '/^##|^# START|^# END/bskip' -e '/^#/d' -e ':skip' file

这比 John1024 的回答更冗长,但也有效:

sed -r 's/# ((START)|(END)).*/## /;/^#[^#].*/d;s/## ((START)|(END))/# /;' sample.conf

把#START/END注释转成受保护的##格式,然后,做转换,再转换回#START/END。

首先我监督了 'no-/p'-要求,那么显而易见的解决方案是:

sed -r '/# (START)|(END).*/p;/^#[^#].*/d' sample.conf 

您可以使用简单的 print-pattern /p,而不是删除复杂的 delete-pattern /d。

请注意,[^S][^T][^A][^R][^T] 将匹配“END”(带有 2 个尾随空格 - 可能不太可能,但如果另一个 3 或 5 个字母的异常需要处理,它会变得很难看,如果它不是还没有。