用awk过滤500个文件,然后cat结果到单个文件

aka*_*use 5 bash awk cat

我在一个包含几千个文件的目录中,但我要过滤的所有文件都具有以下语法: *.imputed.*_info

我想使用 awk 过滤掉每个文件中第 5 列数据的值 > 0.50 的记录,我可以使用:awk '{if($5 >= .5) {print}}' filename.

那也奏效了。然后我尝试遍历所有 500 个左右的文件并连接每个符合此条件的记录。

我尝试了以下但我没有得到正确的语法。

touch snplist.txt
for name in *.imputed.*_info; do
    snps="awk '{if($5 >= .5) {print}}' $name"
    cat snplist.txt "$snps" > snplist.txt
done
Run Code Online (Sandbox Code Playgroud)

Kus*_*nda 14

您的代码会在每次迭代中覆盖输出文件。你实际上也没有打电话awk

你想做的是

awk '$5 >= 0.5' ./*.imputed.*_info >snplist.txt
Run Code Online (Sandbox Code Playgroud)

这将立即调用awk您的所有文件,并按照 shell 扩展通配模式的顺序一个一个地遍历它们。如果文件中任何行的第 5 列大于或等于 0.5,则该行将被输出(进入snplist.txt)。这是因为默认操作(如果没有操作({...}块)与条件相关联)是输出当前行。

如果您有大量文件(数千个),这可能会生成“参数列表太长”错误。在这种情况下,您可能需要循环:

for filename in ./*.imputed.*_info; do
    awk '$5 >= 0.5' "$filename"
done >snplist.txt
Run Code Online (Sandbox Code Playgroud)

请注意, 的结果awk不需要存储在变量中。在这里,它只是输出并且循环(因此循环内的所有命令)被重定向到snplist.txt.

对于数千个文件,这将非常慢,因为awk需要为每个文件单独调用。

为了加快速度,如果您有太多文件无法调用awk,您可以考虑使用xargs如下方法:

printf '%s\0' ./*.imputed.*_info | xargs -0 awk '$5 >= 0.5' >snplist.txt
Run Code Online (Sandbox Code Playgroud)

这将创建一个文件名列表,printf并将它们xargs作为空终止列表传递给。该xargs工具需要这些,并开始awk尽可能多的人尽可能一次,分批。整个管道的输出将被重定向到snplist.txt.

这种xargs替代方法假设您使用的是 Unix,例如 Linux,它有一个xargs命令来实现非标准-0选项来读取以空字符结尾的输入。它还假设您正在使用一个 shell,比如bash,它有一个内置的 printf实用程序(kshOpenBSD 上的默认 shell,在这里不起作用,因为它没有这样的内置实用程序)。


对于zsh外壳(即不是bash):

autoload -U zargs
zargs -- ./*.imputed.*_info -- awk '$5 >= 0.5' >snplist.txt
Run Code Online (Sandbox Code Playgroud)

这使用zargs,它基本上是xargs作为可加载的zshshell 函数的重新实现。有关更多信息,请参阅zargs --help(加载函数后)和zshcontrib(1)手册。


Gil*_*not 5

只需这样做:

awk '$5 >= .5' *.imputed.*_info > snplist.txt
Run Code Online (Sandbox Code Playgroud)