![删除除第一次出现之外的所有行](https://linux22.com/image/97580/%E5%88%A0%E9%99%A4%E9%99%A4%E7%AC%AC%E4%B8%80%E6%AC%A1%E5%87%BA%E7%8E%B0%E4%B9%8B%E5%A4%96%E7%9A%84%E6%89%80%E6%9C%89%E8%A1%8C.png)
给定一个以空格分隔的文本文件,在第一列中查找模式。如果找到,保留第一个出现的行并删除其他行:
输入(模式 = 1234):
1234 1111 2222
5678 3333 4444
1234 5678 9012
5678 1234 5678
1234 9786 5432
预期输出:
1234 1111 2222
5678 3333 4444
5678 1234 5678
答案1
因此,您想要打印第一个字段不是指定值的所有行,并打印匹配的第一行。
awk -vF="$1" '{ if ($1 != F) { print; } else {if (!seen) { print ; seen=1}}}'
seen
利用 awk 变量(在本例中)最初值为 0 的事实。
答案2
保留第一个匹配行,并使用 GNU sed 删除所有后续匹配行:
sed -e '/^1234/{x;/./!{x;h;b;};d}' file
解释:
/^1234/
当模式缓冲区匹配 ^1234 时
x
- 交换模式和保存缓冲区(在第一次匹配时,保存缓冲区将为空,因此模式缓冲区现在是空的)
/./!
- 模式缓冲区现在是空的吗?
{x;h;b;}
- 然后交换 (x) 模式和保持缓冲区(这会将当前行放回到模式缓冲区中),将模式缓冲区复制到旧缓冲区 (h),并分支到该行的执行结束 (b) -即加载下一行并再次启动 sed 代码。最后的 (d) 删除不会运行。
d
- 第一个匹配之后,保留缓冲区将包含 macthing 行的副本,因此上面的 {x;h;b;} 块将不会执行 - 相反,当前行被删除,程序结束,加载下一行进入模式缓冲区,程序再次启动。