Bash:将结果输出到文件的操作未按预期进行

Bash:将结果输出到文件的操作未按预期进行,bash,shell,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 12j34j234j123j4

我有一个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
chinegro $ > cut -f 2 input.tsv | sort >/dev/null
output blablablalblalblalblalba
chinegro $ > 
我的目标是:取出第二列,对其进行排序,并在tsv文件中返回唯一值

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

在terminal中运行此操作花费了很长时间(
请注意,该文件有7000行
。如果您只需在上面提供的20行数据上使用上述代码,它将很快完成。)

然而,如果我像下面这样天真地做,它会做得非常快

cut-f2 input.tsv>output1.tsv

然后

sort output1.tsv>output2.tsv

uniq output2.tsv>output\u final.tsv

那么为什么
cut-f2 input.tsv | sort | uniq>output | u final.tsv
代码要花很长时间才能运行呢?我写错了吗

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

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-f2 input.tsv | sort>/dev/null
时,终端就像下面一样挂在那里,根本不返回任何内容:

 chinegro $ > cut -f 2 input.tsv | sort >/dev/null
通常,当作业完成时,终端应如下所示:

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
chinegro $ > cut -f 2 input.tsv | sort >/dev/null
output blablablalblalblalblalba
chinegro $ > 

管道不应该有太大的区别

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

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)
每次几次并记录时间

然后你可能想问一个关于:-)的问题,关于如何最好地完成你想做的工作,而不是预先假设需要
cut
sort
uniq
。太多的人通过陈述他们正在使用的工具来不必要地限制他们的解决方案空间。您应该仅说明问题,并且仅在绝对需要时限制解决方案空间

首先,您可以使用
sort-u
放弃
uniq
,甚至还有更好的方法使用不同的工具,例如:

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

更新之后:

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

real    0m0.027s
user    0m0.026s
sys 0m0.008s
您可以看到它需要大约三十分之一秒(user+sys=0.034s)的CPU时间

因此,您很可能在原始命令本身中出错。如果很长一段时间没有返回提示,这通常表示您已经省略了输入文件名,例如:

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


因此,我敦促您检查您的实际命令,特别是考虑到您的最后一个命令使用了
output.tsv
作为输入文件。这是错误的,如果是打字错误,您应该仔细检查您向我们显示的其他命令是否是您正在使用的实际命令。

在我的笔记本电脑上,您对7000行的命令是即时的,但不起作用,因为
cut-f2
没有按预期工作。此代码段运行速度很快:

 while read a b c ; do echo "$b" ; done < input.tsv | sort | uniq >| output_final.tsv
在读取a b c时;做回显“$b”;完成| output|u final.tsv

最后一个
|
代表覆盖。

您的管道示例应该可以工作,对于7K行应该很快。你能提供一些关于系统设置的详细信息(uname-a、可用内存等)以及每个设置的具体时间,而不是“永远”和“非常快”。@tolanj
uname-a
returns
Darwin Thomass-MacBook-Pro.local 13.4.0达尔文内核版本13.4.0:Sun Aug 17 19:50:11 PDT 2014;root:xnu-2422.115.4~1/RELEASE\u X86\u 64 X86\u 64
。我希望它能很快完成,但事实并非如此@chepner,当我将任务分解为单独的子任务时,处理这些任务需要几毫秒的时间。但是,当我运行一行代码时,它实际上需要花费很长时间,而且工作永远不会完成。这就是我所说的永远。它的作用与
相同,但如果文件已经存在,它也会覆盖该文件。
只有在设置了
noclobber
选项时才是必需的。是的,但由于您不想选中
noclobber
,因此使用
@Chinegro更安全,您将看不到任何带有
/dev/null
的输出,它将输出发送到“位桶”以消除其对计时的影响。在(user+sys)中执行大约三十分之一秒的完整命令意味着您的问题在别处。我将更新答案。文件名只是一个输入错误,但我传入了正确的文件。以及是否将结果输出到
/dev/null
或文件
>output1.tsv
。它仍然挂在那里。@Chinegro,你的评论有冲突。你说它只是挂起,但这不受时间限制的事实的支持,时间限制只给了很短的秒数,这只有在进程结束时才会发生。这正是问题所在:时间限制只给了很短的秒数,这意味着进程必须已经完成,我确实设法在tsv文件中看到了输出。但当我删除时间时,它就永远挂在那里。我的问题一直是关于这场冲突。