如何重复执行同一命令的grep行?

时间:2019-05-23 10:14:08

标签: grep

我有一个用空格分隔的文件,如下所示:

$ cat in_file
GCF_000046845.1_ASM4684v1_protein.faa WP_004920342.1 Chal_sti_synt_C
GCF_000046845.1_ASM4684v1_protein.faa WP_004927566.1 Chal_sti_synt_C
GCF_000046845.1_ASM4684v1_protein.faa WP_004919950.1 FAD_binding_3
GCF_000046845.1_ASM4684v1_protein.faa WP_004920342.1 FAD_binding_3

我正在使用以下利用grep的shell脚本搜索字符串:

$ cat search_script.sh
grep "GCF_000046845.1_ASM4684v1_protein.faa WP_004920342.1" Pfam_anntn_temp.txt
grep "GCF_000046845.1_ASM4684v1_protein.faa WP_004920342.1" Pfam_anntn_temp.txt

问题是我希望每个grep命令仅返回它找到的字符串的第一个实例,该字符串是前一个相同grep命令输出的排他性

我需要一个看起来像这样的输出:

$ cat out_file
GCF_000046845.1_ASM4684v1_protein.faa WP_004920342.1 Chal_sti_synt_C
GCF_000046845.1_ASM4684v1_protein.faa WP_004920342.1 FAD_binding_3

其中第1行专门是第一个grep命令的输出,而第2行专门是第二个grep命令的输出。我该怎么办?

P.S。我在一个大文件(> 125,000行)上运行它。因此,search_script.sh主要由唯一的grep命令组成。正是这些命令的执行使我的下游分析更加混乱。

2 个答案:

答案 0 :(得分:1)

我假设您是根据search_script.sh的内容自动生成in_file的。如果您可以计算重复一次相同的grep命令的次数,则可以只使用一次grep并使用head,例如,如果您知道自己将重复使用两次:

grep "foo" bar.txt | head -2

将在bar.txt中输出前两个出现的“ foo”。

如果必须分别执行grep命令,例如,如果grep命令之间还有其他代码,则可以混合使用headtail

grep "foo" bar.txt | head -1 | tail -1

Some other commands...

grep "foo" bar.txt | head -2 | tail -1
  • head -n显示输入的前n
  • tail -n显示输入的最后n

如果您确实必须始终使用相同的命令,但要确保输出始终不同,那么我想到的唯一方法是使用临时文件和复杂的命令序列:

 cat foo.bar.txt.tmp 2>&1 | xargs -I xx echo "| grep -v \\'xx\\' " | tr '\n' ' '  | xargs -I xx sh -c "grep 'foo' bar.txt xx | head -1 | tee -a foo.bar.txt.tmp"

因此,为了解释该命令,假设将foo作为搜索字符串,将bar.txt作为文件名,则foo.bar.txt.tmp是临时文件的唯一名称。临时文件将保存已经输出的字符串:

  • cat foo.bar.txt.tmp 2>&1:输出临时文件的内容。如果不存在,则将向stdout输出一条错误消息(这很重要,因为如果输出为空,则该命令的其余部分将不起作用。)
  • xargs -I xx echo "| grep -v \\'xx\\' "| grep -v添加到临时文件中每一行的开头,grep -v something排除包含something的行。
  • tr '\n' ' '用空格替换换行符,以在单个字符串上包含grep -v的序列。
  • xargs -I xx sh -c "grep 'foo' bar.txt xx | head -1 | tee -a foo.bar.txt.tmp"运行新命令grep 'foo' bar.txt xx | head -1 | tee -a foo.bar.txt.tmp,用先前的输出替换xxxx应该是排除先前输出的grep -v的序列。
  • head -1确保一次只输出一行
  • tee -a foo.bar.txt.tmp将新输出附加到临时文件。

只需确保在脚本末尾清除临时文件rm *.tmp

答案 1 :(得分:0)

如果我提出的问题正确,并且您想根据每行的最后一个字段删除重复项,请尝试执行以下操作(对于awk,这应该是一件容易的事)。

awk '!a[$NF]++'  Input_file