是否可以使用正则表达式删除列表中的特定重复字符?

是否可以使用正则表达式删除列表中的特定重复字符?

我有一个列的列表,其中包含约 100 行,其中一些行是重复的,我的目的是摆脱具体的重复行并仅保留复制,而其他行保持不变。

我正在处理的文件的摘录:

V(Mn9)   
V(C1,H3) 
V(Mn6)   
V(Mn6)   
V(C4,H6) 
V(Mn9)   
V(Mn9)   
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)   
V(C1,C4) 
C(Mn9)   
C(Mn6)   
C(C1)    
C(C4)    
C(Mn9)   
C(Mn6)   
V(C1,H2) 
V(Mn9)   
V(Mn6)   
V(C4,H5)

我的目的是删除所有包含 C(Xx0-9) 的重复行并保留其中之一并保留 V(Xxx..)。

我寻求的结果:

V(Mn9)   
V(C1,H3) 
V(Mn6)   
V(Mn6)   
V(C4,H6) 
V(Mn9)   
V(Mn9)   
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)   
V(C1,C4) 
C(C1)    
C(C4)    
C(Mn9)   
C(Mn6)   
V(C1,H2) 
V(Mn9)   
V(Mn6)   
V(C4,H5)

我使用了命令:

sed '0,/C(Mn9)/{/C(Mn9)/d}' inputfile.txt | sed '0,/C(Mn6)/{/C(Mn6)/d}'

它正在工作,但对于整个文件来说还不够好,因为有很多 C(Xx1-50),我想使用正则表达式,但我不知道如何,这就是为什么我需要你的帮助。

答案1

$ awk '!(/^C\(..[0-9])$/ && seen[$0]++)' file
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(Mn9)
C(Mn6)
C(C1)
C(C4)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)

上面假设示例输入中的可见字符之前/之后没有空格。如果这样做,则删除它们,例如:

$ awk '{gsub(/^[[:space:]]+|[[:space:]]+$/,"")} !(/^C\(..[0-9])$/ && seen[$0]++)' file
V(Mn9)
V(C1,H3)
V(Mn6)
V(Mn6)
V(C4,H6)
V(Mn9)
V(Mn9)
V(C1,Mn6)
V(C4,Mn9)
V(Mn6)
V(C1,C4)
C(Mn9)
C(Mn6)
C(C1)
C(C4)
V(C1,H2)
V(Mn9)
V(Mn6)
V(C4,H5)

答案2

我建议使用sed收集保留空间中的行来检查它们之前是否出现过:

 sed -n 'H;G;/^\(C([^)]*)\).*\1 *\n/!P'
  • H将当前行追加到保留空间
  • G将保留空间与我们见过的所有行附加到模式空间
  • C([^)]*)是这些模式之一C(…)^将其锚定到行的开头,并且它被 包围\(…\),因此可以\1稍后反向引用。我们需要\1 *\n作为模式,带有换行符(在可能的空格之后)以避免匹配末尾新添加的行。因此整个模式/^\(C([^)]*)\).*\1 *\n/与具有重复项的行匹配C(…),因此仅当这!不匹配时,
  • P-n在第一个换行符之前打印所有内容(= 没有附加的保留空间),而默认输出被该选项抑制

请注意,根据您的sed版本和文件大小,这可能会失败,因为随着时间的推移,所有行都将存储在内存中。

相关内容