我将这些文件放在目录中:y y1 y2 y3
运行此命令:
ls y* | xargs -i basename {}|xargs -i sed "s/{}//g"
产生这个:
1
2
3
有人可以解释原因吗?!我希望它什么都不产生 - 运行sed四次,每个文件一次,并且每次都删除文件名。但实际上看起来它正在将sed与{}设置应用于第一个文件,在y1 y2 y3的列表上
这是Solaris 10
答案 0 :(得分:2)
xargs
-i
sed
...命令的输入是:
y
y1
y2
y3
该命令将读取行y
并执行sed
s/y//g
,它从标准输入读取。标准输入是继承的,因此它将具有与其标准输入相同的管道,并且可能能够读取剩余的输入:
y1
y2
y3
命令sed s/y//g
将从每行删除y
:
1
2
3
但是,如果xargs
在执行第一个sed
命令之前消耗所有输入,那么sed
命令将没有剩余的输入来读取,并且什么都不做。
答案 1 :(得分:2)
当我在我的linux盒子上尝试这个时,我得到的结果不一致。有时123,有时(大多数时间)23,有时12。这是最右边的xargs
和它产生的任何sed
之间的一种微妙的缓冲竞争条件。
解析命令行:
ls y*
将输出4行y,y1,y2和y3;缓冲不相关xargs -i basename {}
会读取它们并按顺序启动basename y
,basename y1
,basename y2
,basename y3
;输出与我们的输入相同,是行缓冲的,因为每一行来自不同的进程。xargs -i sed "s/{}//g"
,对于它读取的每一行X(稍后会详细介绍),启动sed "s/X//g"
sed "s/X//g"
过滤掉它在其读取的行中看到的每个X 它变得棘手:最后两个命令从同一个流中读取输入。该流由序列中的多个不同过程产生。根据多种因素(系统负载,调度),输出可能会以非常不同的时序模式出现。
让我们假设他们都非常快。然后,右侧xargs
可以在单个块中读取所有四行。在这种情况下,任何sed
s都没有输入,因此根本没有输出。
另一方面,如果它们非常慢,则在第一次读取尝试时,右侧xargs
可能只有一行可用。那条线将是“y”。 xargs
会将第一个sed
生成为sed "s/y//g"
,这将消耗所有剩余输入(y1,y2,y3),条带y
和输出1 ,2,3,。这是相同的解释,更明确的排序。
basename
写“y”。xargs
读“y”,产生sed s/y//g
。 xargs
现在等待sed
完成。basename
写“y1”; sed
读取“y1”,写入“1”basename
写“y2”; sed
读取“y2”,写入“2”basename
写“y3”; sed
读取“y3”,写入“3”xargs
已完成; sed
读取EOF并停止xargs
尝试继续,读取EOF并停止对我的12个案例不确定。可能GNU xargs
在读取后续可用输入之前不等待其子项完成,并从第一个sed
中抢夺了“y3”行。
在任何情况下,您只需在同一作者上设置一个多个并发读者的管道,这会产生大多数不确定的结果。 要避免。
如果您希望对每个文件进行操作,可以通过指定sed
使用的文件名来避免(注意最终的{}):
ls y* | xargs -i basename {} | xargs -i sed "s/{}//g" {}
如果您想要的是跨产品类型的结果(从每个文件中删除每个文件名),您需要安排生成文件列表的次数与文件一样多。如果您仍然使用它,请加xargs
一个。
希望这有帮助。