使用awk选择特定单词而忽略其他单词

时间:2018-02-18 23:22:25

标签: unix awk

让我们说我有一个非常长的文件与物种及其出现。在我的情况下,我想保留物种中的一些物种:CHU,NEU,RNE,SCR,TDF。例如,我的原始矩阵是:

Species_A; CHU, NEU, TUC, SCR
Species_B; CHU, NEU, RNE, SCR, TDF
Species_C; COR, NEU, SAL, TDF
Species_D; CHU, RNE, SCR, TDF
Species_D; SCR, TDF

我想只保留那些出现CHU,NEU,RNE,SCR,TDF的物种,同时排除其他遗址:

Species_B; CHU, NEU, RNE, SCR, TDF
Species_D; CHU, RNE, SCR, TDF
Species_D; SCR, TDF

我认为一个选项可能是:

awk -F";" ' $ 2 / CHU /&& / NEU /&& / RNE /&& / SCR /&& / TDF / {print}'文件

但这也包括那些不需要的网站(例如SAL,TUC)。

欢迎任何提示。

1 个答案:

答案 0 :(得分:4)

Awk方法1:正则表达式

$ awk  '/;([[:blank:],]*(CHU|NEU|RNE|SCR|TDF))+$/' file
Species_B; CHU, NEU, RNE, SCR, TDF
Species_D; CHU, RNE, SCR, TDF
Species_D; SCR, TDF

这只打印那些与正则表达式;([[:blank:],]*(CHU|NEU|RNE|SCR|TDF))+$匹配的行。

Awk方法2:循环

尝试:

$ awk  '{for (i=2;i<=NF;i++) if (!($i~/^(CHU|NEU|RNE|SCR|TDF)/)) next} 1' file
Species_B; CHU, NEU, RNE, SCR, TDF
Species_D; CHU, RNE, SCR, TDF
Species_D; SCR, TDF

如何运作

  • for (i=2;i<=NF;i++) if (!($i~/^(CHU|NEU|RNE|SCR|TDF)/)) next

    这会循环第一个之后的所有单词。如果这些单词中的任何一个单词不以您批准的3个字母的字符串开头,那么我们跳过其余的命令并跳转到next行重新开始。

  • 1

    这是awk的印刷版速记。 (当然,只有在未触发上述next命令时才会执行此操作。)

使用sed

使用与方法1相同的逻辑:

$ sed -En  '/;([[:blank:],]*(CHU|NEU|RNE|SCR|TDF))+$/p' file
Species_B; CHU, NEU, RNE, SCR, TDF
Species_D; CHU, RNE, SCR, TDF
Species_D; SCR, TDF

使用grep

使用相同的正则表达式逻辑:

$ grep -E  ';([[:blank:],]*(CHU|NEU|RNE|SCR|TDF))+$' file
Species_B; CHU, NEU, RNE, SCR, TDF
Species_D; CHU, RNE, SCR, TDF
Species_D; SCR, TDF