删除可能具有不同间距的重复行,但忽略以 # 开头的行

删除可能具有不同间距的重复行,但忽略以 # 开头的行

这是一个后续先前的问题。我使用此语法是为了删除重复行,即使字段的间距不同

awk '{$1=$1};!NF||!seen[$0]++' /tmp/fstab

现在我想排除以 开头的行#。所以我使用这个语法

awk '/^#/ || "'!'"'{$1=$1};!NF||!seen[$0]++' /tmp/fstab
-bash: !: event not found

我的语法有什么问题?

答案1

怎么样

awk '!NF||$1~/^#/ {print; next} {$1=$1} !seen[$0]++' /tmp/fstab

这将立即打印任何空行或其第一个字段以 开头的行#,然后跳过执行,以便绕过任何进一步的代码。只要尚未遇到其他所有行,就会重建并打印它们。

$1~/^#/检查 if而不是将匹配应用于整行(即简单地)的原因/^#/是,这样我们还可以捕获 前面#有空格的注释行。尽管联机帮助fstab页要求为了符合注释行的资格,第一的字符必须是 a #,正如 @StephenKitt 指出的,Linux 实现libmount将跳过前导空格并接受一行作为注释第一个非空白字符是 a #

答案2

由于bash正在抱怨(而不是awk)并且您的周围有单引号,因此!问题很明显:您正在退出 的命令块awk

awk '{$1=$1} /^#/ || !seen[$0]++' file 

即先进行操作,然后进行检查。缺点:也会删除/减少注释中的空格,但不会删除此类重复项。通过首先缓冲该行来避免这种情况:

awk  '{a=$0 ; $1=$1}  /^#/ || !seen[$0]++ {print a}' file

输入:

#comment
duplicate line
#comment
duplicate    line 
not duplicate
not duplicate 2
duplicate        line
#comment2
#comment2
#comment 3
#comment      3

输出(第一个代码)

#comment
duplicate line
#comment
not duplicate
not duplicate 2
#comment2
#comment2
#comment 3
#comment 3

输出(第二个代码)

#comment
duplicate line
#comment
not duplicate
not duplicate 2
#comment2
#comment2
#comment 3
#comment      3

答案3

GNU sed扩展正则表达式模式打开-E

sed -Ee '
  # print empty|blank|comment lines
  /^\s*(#|$)/b
  s/\s+/ /g;s/^ | $//g;G;        # squeeze whitespace n append previous unique lines
  /^([^\n]*)\n(.*\n)?\1(\n|$)/d; # delete if seen
  P;h;d;                         # print seen first time then update seen list
'  file

相关内容