更改xargs(或GNU并行)参数中的文本



我有一个程序,可以用两种方式运行:单端或成对端模式。语法如下:

program <output-directory-name> <input1> [input2]

其中需要输出目录和至少一个输入。如果我想在三个文件上运行这个,比如样本A、B和C,我会使用类似find的xargs或parallel:

user@host:~/single$ ls
sampleA.txt  sampleB.txt  sampleC.txt
user@host:~/single$ find . -name "sample*" | xargs -i echo program {}-out {}
program ./sampleA.txt-out ./sampleA.txt
program ./sampleB.txt-out ./sampleB.txt
program ./sampleC.txt-out ./sampleC.txt
user@host:~/single$ find . -name "sample*" | parallel --dry-run program {}-out {}
program ./sampleA.txt-out ./sampleA.txt
program ./sampleB.txt-out ./sampleB.txt
program ./sampleC.txt-out ./sampleC.txt

但当我想在"成对端"模式下运行程序时,我需要给它两个输入。这些都是相关的文件,但它们不能简单地连接在一起——您必须将两者作为输入来运行程序。文件命名合理,例如sampleA_1.txt和sampleA_2.txt。

我希望能够在命令行上使用类似xargs(或者最好是并行的)的东西轻松地创建这个:

user@host:~/paired$ ls
sampleA_1.txt  sampleB_1.txt  sampleC_1.txt
sampleA_2.txt  sampleB_2.txt  sampleC_2.txt
user@host:~/paired$ find . -name "sample*_1.txt" | sed/awk? | parallel ?
program ./sampleA-out ./sampleA_1.txt ./sampleA_2.txt
program ./sampleB-out ./sampleB_1.txt ./sampleB_2.txt
program ./sampleC-out ./sampleC_1.txt ./sampleC_2.txt

理想情况下,该命令会去掉_1.txt来创建输出目录名(sampleA-out等),但我确实需要能够接受该参数,并将第二个输入的_1更改为_2。

我知道这对于脚本来说非常简单——我在Perl中使用了一个快速的正则表达式替换来实现这一点。但我希望能够用一句快速的俏皮话做到这一点。

提前谢谢。

我在Perl中用一个快速的正则表达式替换实现了这一点。但我希望能够用一句快速的俏皮话做到这一点。

Perl也有一行代码,就像sedawk一样

find . -name "sample*_1.txt" | perl -pe 's/_1.txt$//' | parallel program {}-out {}_1.txt {}_2.txt

-e标志表示"下一个参数是程序文本";-p标志表示"程序应循环运行;对于每一行输入,将$_设置为该行,然后运行程序,然后打印$_"。)

使用sedxargs,您可以执行以下操作:

find . -name "sample*_1.txt" | sed -n 's/_1..*$//;h;s/$/_out/p;g;s/$/_1.txt/p;g;s/$/_2.txt/p' | xargs -L 3 echo program

即:sed创建三个参数,xargs -L 3用三个参数组成命令行。

假设目录中每对总是有两个文件,并且假设它们按find正确排序(这可以通过findsort的管道结果来确保),那么xargs -l 2可能会完成这项工作。这个命令告诉xargs在它执行的每个命令行上放置2个连续的传入参数。

较短的版本:

parallel --xapply program {1.}.out {1} {2} :::: <(ls *_1.txt) <(ls *_2.txt)

但这只适用于每个_1.txt都有匹配的_2.txt的情况,反之亦然。

最新更新