Bash:管道结果输出文件未按预期工作

时间:2014-10-29 12:13:21

标签: bash shell

我有一个包含3列和7000行的tsv文件。它看起来像这样:

1341234jh34h123h    abc 1
23k4j123j4123h4h    abc 1
123j41j234j234jj    bbb 1
1234jj1324j123j4    ccc 1
2134j1234j1234jj    bbb 1
1324j123j4123j41    abc 1
132j412j34j1234j    ddd 1
12j34j1234j4j234    abc 1
12j34j234j123j43    abc 1
123j412j341234jj    abc 1
123j4j234j132j4j    abc 1
123k41k234123l4l    bbb 1
2k134k2134k23k4k    abc 2
132k4k132k423k4k    ddd 1
k234k123k4k34k34    bbb 1
23k4k34k3k43k43k    abc 1
l234k34l3l43;3;4    abc 1
k234k23k42k342k3    bbb 1
q,wmeqwjneqkwjen    ddd 1
llqkweqweqjwejqw    bbb 1

我的目标是:取出第二列,对其进行排序并在tsv文件中返回唯一值。

我在终端上写的代码是:cut -f 2 input.tsv | sort | uniq > output_final.tsv

在终端(note that the file has 7000 rows中运行此操作需要花费很长时间。如果您只是在上面提供的20行数据中使用上述代码,那么它将非常快速地完成。)

然而,如果我以一种天真的方式做到这一点,就像下面这样,它会很快完成。

cut -f 2 input.tsv > output1.tsv

然后

sort output1.tsv > output2.tsv

uniq output2.tsv > output_final.tsv

那么为什么cut -f 2 input.tsv | sort | uniq > output_final.tsv代码会永远运行?我写错了吗?

BIG UPDATE:所以我做了time @paxdiablo建议的事情。有趣的是,我发现了

time (cut -f 2 input.tsv >/dev/null)

real    0m0.017s
user    0m0.015s
sys 0m0.002s

time (cut -f 2 input.tsv | sort >/dev/null)

real    0m0.025s
user    0m0.021s
sys 0m0.006s

time (cut -f 2 input.tsv | sort  | uniq >/dev/null)

real    0m0.027s
user    0m0.026s
sys 0m0.008s

因此,这些工作需要很少的时间。但是当我运行cut -f 2 input.tsv | sort >/dev/null时,终端就像下面那样挂在那里而根本没有返回任何内容:

 chinegro $ > cut -f 2 input.tsv | sort >/dev/null

通常,当作业完成时,终端应该是这样的:

chinegro $ > cut -f 2 input.tsv | sort >/dev/null
output blablablalblalblalblalba
chinegro $ > 

2 个答案:

答案 0 :(得分:2)

管道不应该产生太大的影响。

我要做的第一件事是通过运行以下命令来查看导致问题的组件:

time ( cut -f 2 input.tsv >/dev/null )
time ( cut -f 2 input.tsv  | sort >/dev/null)
time ( cut -f 2 input.tsv  | sort | uniq >/dev/null)

每次几次并记录时间。

然后你可能想问a suitable site :-)关于如何最好地完成你想做的工作的问题,而不是假设cutsort和{ {1}}将是必要的。很多人通过陈述他们正在使用的工具来不必要地限制他们的解决方案空间。您应该声明只是问题,并且如果绝对需要,则仅限制解决方案空间。

首先,您可以使用uniq放弃uniq,甚至可能有更好的方式使用不同的工具,例如:

sort -u

并且,在您更新后:

awk '{keys[$2] = 1} END {for (key in keys) { print key } }' input.tsv

你可以看到它耗费了大约三十分之一秒(用户+ sys = 0.034s)的CPU时间。

因此,您可能在原始命令本身中遇到了错误。如果它没有返回到时间的提示,那通常表示您已将输入文件名留下,例如:

time (cut -f 2 input.tsv | sort  | uniq >/dev/null)

real    0m0.027s
user    0m0.026s
sys 0m0.008s

并且cut -f 2 | sort 将永远等待,直到您输入一些行,然后按 CTRL-D 指示文件结束(您可以通过输入 CTRL-D来测试此行当它正在运行并查看提示是否返回时。)

所以我建议你检查一下你的实际命令,特别是考虑到最后一个人使用cut作为输入文件。这是错误的,如果它是一个错字,你应该仔细检查你向我们展示的其他命令是你正在使用的实际的

答案 1 :(得分:0)

在我的笔记本电脑上,您对7000行的命令是立即执行的,但由于cut -f 2无法按预期工作,因此无效。这段代码很快就可以了:

 while read a b c ; do echo "$b" ; done < input.tsv | sort | uniq >| output_final.tsv

最后>|代表覆盖。