【问题标题】:Passing filename and file content arguments to perl script with GNU parallel使用 GNU 并行将文件名和文件内容参数传递给 perl 脚本
【发布时间】:2013-09-08 04:33:40
【问题描述】:

我正在尝试并行化 perl 脚本的使用。 perl 脚本的输入和输出参数从目录中获取文件名。这对于 gnu 并行很简单。

ls dir | parallel script.pl --input {} --output {.}.out

但是,脚本中的一个附加参数要求我从每个文件中获取第一行和最后一行、第二列的值......类似于

ls dir | parallel script.pl --input {} --output {.}.out --otherargs range:{1}-{2}

其中 {1} 和 {2} 派生自先前/同时使用 awk 或 sed 以获取这些值,例如

awk 'NR==1 {print $2}; END {print $2}' 

但是我应该在哪里放置(如何放置)这个类似 awk 的步骤在“工作流程”中以允许 perl 脚本使用它?

看着

Change text in argument for xargs (or GNU Parallel)

正确的方法就是这样做吗?

ls | parallel script.pl --input {} --output {.}.out --otherargs range:{1}-{2} :::: <(awk 'NR==1 {print $2}) <(awk 'END {print $2})

谢谢。

【问题讨论】:

  • awk 'NR==1 {print $2}' 会在哪里接受它的输入?也来自ls
  • 是的,就是这样。 script.pl 和 awk 都从文件列表中获取输入。

标签: perl awk arguments gnu-parallel


【解决方案1】:

不清楚你想要什么。如果不是这样,请给我们一个完整的输入示例和想要的输出。

ls | parallel script.pl --input {3} --output {3.}.out --otherargs range:{1}-{2} :::: <(ls | awk 'NR==1 {print $2}') <(ls | awk 'END {print $2}') -

或:

parallel script.pl --input {3} --output {3.}.out --otherargs range:{1}-{2} :::: <(ls | awk 'NR==1 {print $2}') <(ls | awk 'END {print $2}') <(ls)

浏览教程http://www.gnu.org/software/parallel/parallel_tutorial.html 你的命令行会爱上你的。

【讨论】:

  • 奥莱-谢谢。这正是我的想法。所以 {3} 是第一个 ls 调用的文件名,然后 1 和 2 是由 GNU 并行中的
  • 末尾的 - 指的是标准输入(即 | 之前的东西)。答案已更新为替代。
  • @beckerhopper 我在我们的谈话中做了一个注释,说明这可能是低效的。正如预期的那样,这一行命令需要三次调用ls。我不知道你怎么会喜欢这个解决方案。
【解决方案2】:

这可能是您需要的解决方案:

#!/bin/bash
readarray -t LIST < <(ls)
FIRST=${LIST[0]}; LAST=${LIST[@]:(-1)}
printf '%s\n' "${LIST[@]}" | parallel script.pl --input {} --output {.}.out --otherargs "range:${FIRST}-${LAST}"

bash script.sh 运行它。也许你需要运行排序? &lt;(ls | sort)。我认为即使您有不同的 $FIRST$LAST 来源,这个概念也会随之而来。

使用临时文件的类似概念:

ls > temp
FIRST=$(awk 'NR==1 {print $2}' temp)
LAST=$(awk 'END {print $2}' temp}
parallel script.pl --input {} --output {.}.out --otherargs "range:${FIRST}-${LAST}" < temp

另外我认为这是你真正需要的 awk 命令:

{read -r FIRST; read -r LAST;} < <(awk 'NR==1{print $2;next}{t=$2};END{print t}' temp)

【讨论】:

  • 我明白你在说什么,但这不是使第一个和最后一个数据的获取成为一个串行过程,并且只有对 script.pl 的调用是并行的吗?
  • @beckerhopper 我不太明白你的意思,但你会有不同的结果吗?您还应该注意,您不能两次读取输入,因此您不能让多个进程(并行、awk、awk)读取单个输出 (ls)。您必须首先将输出存储在某个地方,例如缓冲区(本例中为数组),然后相应地获取您的参数。
  • 如果你愿意,你可以调用ls 两次,或者每个进程调用三次,但那是一样的。首先将其输出存储在缓冲区中会更有效。谁知道第二次或第三次之后输出可能已经不同了。
  • 使用tee之类的复制输出的概念是一样的。在内部,它仍然会将输入存储到缓冲区,然后再将其发送到另外两个或更多进程。
  • 好主意。我自己已经回答了这个问题,但还不能发布(声誉太低)。 bash 脚本收集相关数据并将其传递给 perl 脚本。在 GNU 中并行运行 bash 脚本。详细信息即将发布。
【解决方案3】:

我自己的解决方案是一个 bash 脚本,传递给 GNU 并行,但上面的 Ole 更优雅(一个 GNU 并行单行).....收集相关变量并将它们传递给 perl 脚本的 bash 脚本。在 GNU 中并行运行此脚本。

这是 bash 脚本

#!/bin/bash
sample=$1
describer=$(echo ${sample} | sed 's/.sync//') # removes .sync suffix
a=($(awk 'NR==1 {print $2}' ${sample}))
b=($(awk 'END {print $2}' ${sample}))

perl script.pl --input ${describer}.sync --output ${describer}.genepop  
--argument scaffold_1:$a-$b  

紧随其后

ls | parallel bash bash.script.sh

这使得从文件中收集变量成为文件分析的一部分。

感谢您提供鼓舞人心的洞察力 konsolebox。我也应该关注我自己的旧帖子。

Storing text and numeric variable from file to use in perl script

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    • 2022-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多