我很难弄清楚如何删除重复但不完整的文本字符串。使用perl
、awk
或均未成功sed
。
我需要转换:
a b
a b c
a b c d
a b c d e
a b c d x
a b c d z
进入
a b
a b c d e
a b c d x
a b c d z
每个不完整的模式都必须被删除,但(1) 不是每个最终完整且唯一的字符串,以及(2) 不是长度为两个单词的字符串。
我能找到的所有答案都涉及删除相同的重复项。
我很难弄清楚如何删除重复但不完整的文本字符串。使用perl
、awk
或均未成功sed
。
我需要转换:
a b
a b c
a b c d
a b c d e
a b c d x
a b c d z
进入
a b
a b c d e
a b c d x
a b c d z
每个不完整的模式都必须被删除,但(1) 不是每个最终完整且唯一的字符串,以及(2) 不是长度为两个单词的字符串。
我能找到的所有答案都涉及删除相同的重复项。
假设满足以下所有条件:
此文件中的字符串已排序(这意味着,您要删除的“不完整重复项”后面跟着包含它的行)
您只想匹配行的开头,因此例如在以下序列中,第一行不会被删除(第二行包含第一行,但不以相同的序列开头
这与以下非常相似:使用 sed 或 awk,每当下一行以相同内容开头后跟斜杠时,如何删除该行?
这是一个可能的解决方案:
为了便于阅读,可以多行显示:
prev
并跳到下一行。prev" "
(prev
末尾有一个空格) 是否与当前行 ($0
) 的开头(索引 1)匹配。如果不匹配,则打印上一行。split(prev, _) == 2
),则仍然打印它_
只是split(prev, _)
为了提示我不会使用由此产生的数组split
。$0
) 复制到prev
。awk
读取文件完成后,打印最后一行(prev
),除非文件为空。例子:
使用 any
awk
和sort
:" "
中每个字符串末尾的是index()
必需的,这样,a b d
就不会错误地匹配为 的子字符串a b dog
(假设我们只想要全字比较),并且a b e
会与自身匹配(假设我们想要删除完全重复的行以及子字符串行),例如给出这个更全面的示例输入:我们得到了预期的输出:
通过上述脚本,我们首先对输入进行排序,以便较长的字符串出现在以相同字符开头的较短字符串之前,从而使 awk 可以轻松测试当前字符串是否是前一个字符串的子字符串,然后我们再次排序以获得最终输出。
这种首先排序的方法意味着无论输入的顺序如何它都会起作用,例如:
如果我们还希望输出顺序与上述未排序输入的输入顺序相同,我们可以应用Decorate-Sort-Undecorate 习语,先添加原始行号,然后按顺序排序并在最后删除它们: