我在一个目录中有这些文件:y y1 y2 y3
运行此命令:
ls y* | xargs -i basename {}|xargs -i sed "s/{}//g"
产生这个:
1
2
3
有人可以解释为什么吗?!我希望它不会产生任何结果 - sed 运行四次,每个文件一次,并且每次都删除文件名。但实际上它看起来像是在应用 sed 并将 {} 设置为第一个文件,在 y1 y2 y3 的列表中
这是 Solaris 10
我在一个目录中有这些文件:y y1 y2 y3
运行此命令:
ls y* | xargs -i basename {}|xargs -i sed "s/{}//g"
产生这个:
1
2
3
有人可以解释为什么吗?!我希望它不会产生任何结果 - sed 运行四次,每个文件一次,并且每次都删除文件名。但实际上它看起来像是在应用 sed 并将 {} 设置为第一个文件,在 y1 y2 y3 的列表中
这是 Solaris 10
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
当我在我的 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
as sed "s/y//g"
,这将消耗所有剩余的输入 (y1, y2, y3)、stripy
和输出 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 案例。可能 GNUxargs
在读取后续可用输入之前没有等待其子代完成,而是从第一个sed
.
在任何情况下,您只需在同一个 writer 上设置一个具有多个并发读取器的管道,这会产生大部分不确定的结果。 要避免。
如果您想对每个文件进行操作,可以通过指定要使用的文件名来避免sed
(注意最后的 {}):
ls y* | xargs -i basename {} | xargs -i sed "s/{}//g" {}
如果您想要的是跨产品类型的结果(从每个文件中删除每个文件名),您需要安排生成文件列表的次数与文件的数量一样多。xargs
如果您仍然使用它,请加一个。
希望这可以帮助。