我在一个包含几千个文件的目录中,但我要过滤的所有文件都具有以下语法: *.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
实用程序(ksh
OpenBSD 上的默认 shell,在这里不起作用,因为它没有这样的内置实用程序)。
对于zsh
外壳(即不是bash
):
autoload -U zargs
zargs -- ./*.imputed.*_info -- awk '$5 >= 0.5' >snplist.txt
Run Code Online (Sandbox Code Playgroud)
这使用zargs
,它基本上是xargs
作为可加载的zsh
shell 函数的重新实现。有关更多信息,请参阅zargs --help
(加载函数后)和zshcontrib(1)
手册。