[英]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
不是答案 - 而是指出可能的问题。
代码在管道中运行两个过滤器
第一行中的 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 gg
和gg:192
的行之间。
包含192 gg
和gg: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.