为什么并行模式下的xargs不能使用grep?

问题描述 投票:1回答:1
cat gg

给出

192

cat tmpfilelist

给予

android/app/src/main/res/drawable-mdpi/src_assets_images_alerts_iconnotificationsmartpluggreen.png
android/app/src/main/res/drawable-mdpi/src_assets_images_ic_biggames.png  
android/app/src/main/res/drawable-xhdpi/src_assets_images_alerts_iconnotificationsmartpluggreen.png  
android/app/src/main/res/drawable-xhdpi/src_assets_images_ic_biggames.png   
android/app/src/main/res/drawable-xxhdpi  /src_assets_images_alerts_iconnotificationsmartpluggreen.png  
android/app/src/main/res/drawable-xxhdpi/src_assets_images_ic_biggames.png  
gg  
ios/WebRTC.framework/Headers/RTCCallbackLogger.h  
ios/WebRTC.framework/Headers/RTCFileLogger.h  
ios/WebRTC.framework/Headers/RTCLogging.h  

我在开启parralel模式的情况下运行xargs--无法找到所需的文本 "192"。

cat tmpfilelist | \xargs   -P0 -t  -I {} \bash  -c "\grep -C 2 -H -I -r 192 {}" |& \grep -C 3 "192 gg"
bash -c '\grep -C 2 -H -I -r 192 android/app/src/main/res/drawable-xhdpi/src_assets_images_ic_biggames.png'  
bash -c '\grep -C 2 -H -I -r 192 android/app/src/main/res/drawable-xxhdpi/src_assets_images_alerts_iconnotificationsmartpluggreen.png'  
bash -c '\grep -C 2 -H -I -r 192 android/app/src/main/res/drawable-xxhdp/src_assets_images_ic_biggames.png'  
bash -c '\grep -C 2 -H -I -r 192 gg'
bash -c '\grep -C 2 -H -I -r 192 ios/WebRTC.framework/Headers/RTCCallbackLogger.h'  
bash -c '\grep -C 2 -H -I -r 192 ios/WebRTC.framework/Headers/RTCFileLogger.h'  
bash -c '\grep -C 2 -H -I -r 192 ios/WebRTC.framework/Headers/RTCLogging.h'  

当我禁用parralel模式时,它成功地在文件 "gg "中找到了文本 "192"。

cat tmpfilelist | \xargs   -t  -I {} \bash  -c "\grep -C 2 -H -I -r 192 {}" |& \grep -C 3 "192 gg"
bash -c '\grep -C 2 -H -I -r 192 android/app/src/main/res/drawable-xhdpi/src_assets_images_ic_biggames.png'  
bash -c '\grep -C 2 -H -I -r 192 android/app/src/main/res/drawable-xxhdpi/src_assets_images_alerts_iconnotificationsmartpluggreen.png'  
bash -c '\grep -C 2 -H -I -r 192 android/app/src/main/res/drawable-xxhdp/src_assets_images_ic_biggames.png'  
bash -c '\grep -C 2 -H -I -r 192 gg'  
gg:192  
bash -c '\grep -C 2 -H -I -r 192 ios/WebRTC.framework/Headers/RTCCallbackLogger.h'  
bash -c '\grep -C 2 -H -I -r 192 ios/WebRTC.framework/Headers/RTCFileLogger.h'  

为什么并行模式会破坏grep?还是我在某个地方犯了错误?

非常感谢

linux xargs
1个回答
5
投票

这个问题确实是由于并行执行造成的。问题是当你并行运行时,输出不是确定性的。我创建了一个类似的测试

bash-5.0# ls -alh
total 32K
drwxr-xr-x    9 root     root         288 May 20 17:00 .
drwxr-xr-x    1 root     root        4.0K May 20 17:11 ..
-rw-r--r--    1 root     root           3 May 20 17:00 a
-rw-r--r--    1 root     root           3 May 20 17:00 b
-rw-r--r--    1 root     root           3 May 20 17:00 c
-rw-r--r--    1 root     root           4 May 20 17:00 d
-rw-r--r--    1 root     root           3 May 20 17:00 e
-rw-r--r--    1 root     root           3 May 20 17:00 f
-rw-r--r--    1 root     root          11 May 20 17:00 files

bash-5.0# tail -n +1 *
==> a <==
192
==> b <==
193
==> c <==
192
==> d <==
195

==> e <==
200
==> f <==
198
==> files <==
a
b
c
d
e
f

现在,如果我们运行你的两个命令而不使用最后的grep,输出结果如下所示

无并行

bash-5.0# cat files | \xargs   -t  -I {} \bash  -c "\grep -C 2 -H -I -r 192 {}"
bash -c \grep -C 2 -H -I -r 192 a
a:192
bash -c \grep -C 2 -H -I -r 192 b
bash -c \grep -C 2 -H -I -r 192 c
c:192
bash -c \grep -C 2 -H -I -r 192 d
bash -c \grep -C 2 -H -I -r 192 e
bash -c \grep -C 2 -H -I -r 192 f

有平行的

bash-5.0# cat files | \xargs  -P4 -t  -I {} \bash  -c "\grep -C 2 -H -I -r 192 {}"
bash -c \grep -C 2 -H -I -r 192 a
bash -c \grep -C 2 -H -I -r 192 b
bash -c \grep -C 2 -H -I -r 192 c
bash -c \grep -C 2 -H -I -r 192 d
bash -c \grep -C 2 -H -I -r 192 e
a:192
bash -c \grep -C 2 -H -I -r 192 f
c:192

希望你能看到它是如何影响你的生产线的输出和订单。所以你的问题是,当你做 grep -C 3 192 gg在打印之前,你应该得到3行的信息 192 gg 和3后,其实你确实得到了。

但是 gg:192 被打印出来,因为每条命令都在同一个输出终端上并行发送它们的输出。


0
投票

不是答案--但指出了可能的问题。

该代码在管道中运行两个过滤器

  • grep -C 2 -H -I -r 192 FILENAMe
  • grep -C 3 "192 gg"

第一行的输出将遵循'FILENAME:DATA'的格式。在上面的例子中

gg:192

第二个过滤器是找不到'192 gg'这个模式的。

所以问题可能是,非并行如何产生任何输出?


0
投票

简答

您的最终 grep -C 3 请求3行上下文,围绕 192 gg. 在平行的情况下,这可能或可能不足以找到包含有 gg:192.

详情

在决赛前 grep,你的输出将由一些行组成,比如说。

bash -c \grep -C 2 -H -I -r 192 <filename>

这几行会被回传到stderr,正好在 xargs 各自 bash -c ... 命令,以及该行的

gg:192

的时候,会被回传到stdout。bash -c ... 命令(即涉及到文件的 gg)找到匹配。

在并行的情况下,整个输出都会被管道输送到你的最终的 grep (一旦将stderr和stdout用 |&)可能是这样的,为了简洁起见,我把其他文件名都替换了。

bash -c \grep -C 2 -H -I -r 192 some_file
bash -c \grep -C 2 -H -I -r 192 some_other_file
bash -c \grep -C 2 -H -I -r 192 another_file
bash -c \grep -C 2 -H -I -r 192 gg
bash -c \grep -C 2 -H -I -r 192 and_another_file
bash -c \grep -C 2 -H -I -r 192 yet_another_file
gg:192
bash -c \grep -C 2 -H -I -r 192 and_yet_another_file

在这个例子中 bash -c ... 涉及 and_another_fileyet_another_file 启动的次数 之后 牵涉 gg 启动,但在涉及 gg 写了它的输出(或至少在与该输出相关的任何stdio缓冲区被刷新之前),所以它们出现在包含有 192 gggg:192.

含有以下内容的线条之间的这种间隔行数: 192 gggg:192 (在本例中,2)将取决于时间和在涉及到的任务之后启动的其他并行任务的数量。gg. 这将会有所不同,例如,如果你插入了一个 sleep 语句(如 ... \bash -c "sleep 1; \grep -C ...),那么就会有更多这样的行。 在任何情况下,你都会将它以管道的形式传送到一个 grep -C 3 来提取3行上下文。 如果恰好中间的行数少于3行,那么这个 grep -C 将发现包含 gg:192但如果有3个或更多,那么它将在要求的上下文量之外,不会出现在最终的输出中。

然而,在串行的情况下, gg:192 行保证总是紧接在 192 gg 行,如是。

bash -c \grep -C 2 -H -I -r 192 some_file
bash -c \grep -C 2 -H -I -r 192 some_other_file
bash -c \grep -C 2 -H -I -r 192 another_file
bash -c \grep -C 2 -H -I -r 192 gg
gg:192
bash -c \grep -C 2 -H -I -r 192 and_another_file
bash -c \grep -C 2 -H -I -r 192 yet_another_file
bash -c \grep -C 2 -H -I -r 192 and_yet_another_file

因此,它总是在3行的上下文中。

© www.soinside.com 2019 - 2024. All rights reserved.