繁体   English   中英

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

[英]Why doesn't xargs in parallel mode work with grep?

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  

我在并行模式下运行 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'  

当我禁用并行模式时,它成功在文件“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? 还是我在某个地方犯了错误?

非常感谢

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

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

希望您能看到它如何影响 output 和您的线路订单。 因此,您的问题是,当您执行grep -C 3 192 gg时,您应该在打印192 gg之前获得 3 行,之后获得 3 行,实际上您确实得到了。

但是gg:192稍后打印,因为每个命令在同一个 output 终端上并行发送它们的 output

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

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

  • grep -C 2 -H -I -r 192 文件名
  • grep -C 3“192 gg”

第一行中的 output 将遵循格式“文件名:数据”。 在上面的例子中

gg:192

第二个过滤器不会找到模式“192 gg”。

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

简短的回答

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

细节

在最终的grep之前,您的 output 将包含许多行,例如:

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

xargs启动每个bash -c...命令之前,它们会回显到 stderr,并且该行

gg:192

当相关的bash -c...命令(即涉及文件gg的命令)找到匹配项时,将回显到标准输出。

在并行情况下,整个 output 被输送到您的最终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

In this example, the bash -c... commands involving and_another_file and yet_another_file were launched after the one involving gg was launched, but before the one involving gg wrote its output (or at least, before any stdio buffers associated with that output were flushed ),因此它们出现在包含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 个或更多,那么它将超出所请求的上下文量,并且不会在最终的 output 中。

然而,在串行情况下,保证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 行上下文中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM