GNU Parallel的具体使用
它是什么?
GNUParallel是一个shell工具,为了在一台或多台计算机上并行的执行计算任务,一个计算任务可以是一条shell命令或者一个以每一行做为输入的脚本程序。通常的输入是文件列表、主机列表、用户列表、URL列表或者表格列表;一个计算任务也可以是一个从管道读取的一条命令。GNUParallel会把输入分块,然后通过管道并行的执行。
如果你会使用xargs和tee命令,你会发现GNUParallel非常易于使用,因为GNUParallel具有与xargs一样的选项。GNUParallel可以替代大部分的shell循环,并且用并行的方式更快的完成计算任务。
GNUParallel保证它的输出与顺序执行计算任务时是一样的,这样就可以方便的把GNUParallel的输出做为其它程序的输入。
对于每一行输入,GNUParallel会把这一行做为参数来运行指定的命令。如果没有给出命令,那么这一行会被当做命令执行。多行输入会并行的运行。GNUParallel经常被用于替代xargs或者cat|bash。
指南
本教程展示了绝大多数GNUParallel的功能。旨在介绍GNUParallel中的一个选项,而非讲解真实世界中使用的例子。花一个小时的时间学习本教程,你会由此爱上上命令行。
预备
为了执行本教程中的示例,你首先需要做如下准备:
parallel>=version20130814
安装最新版:
(wget-O-pi.dk/3||curlpi.dk/3/)|bash
这条命令同时也会安装最新版的指南
manparallel_tutorial
本教程的大部分内容同时也兼容旧版本。
abc-file
生成文件:
parallel-kecho:::ABC>abc-file
def-file
生成文件:
parallel-kecho:::DEF>def-file
abc0-file
生成文件:
perl-e'printf"A\0B\0C\0"'>abc0-file
abc_-file
生成文件:
perl-e'printf"A_B_C_"'>abc_-file
tsv_file.tsv
生成文件:
perl-e'printf"f1\tf2\nA\tB\nC\tD\n"'>tsv-file.tsv
num30000
生成文件:
perl-e'for(1..30000){print"$_\n"}'>num30000
num1000000
生成文件:
perl-e'for(1..1000000){print"$_\n"}'>num1000000
num_%header
生成文件:
(echo%head1;echo%head2;perl-e'for(1..10){print"$_\n"}')>num_%header
远程执行:ssh免密码登录$SERVER1和$SERVER2
生成文件:
SERVER1=server.example.com SERVER2=server2.example.net
最后应该成功运行如下命令:
ssh$SERVER1echoworks ssh$SERVER2echoworks
使用ssh-keygen-tdsa;ssh-copy-id$SERVER1建立环境(使用emptypassphrase)
输入源
GNUParallel的输入源支持文件、命令行和标准输入(stdin或pipe)
单个输入源
从命令行读取输入:
parallelecho:::ABC
输出(由于任务以并行的方式执行,顺序可能会有所不同):
A
B
C
文件做为输入源:
parallel-aabc-fileecho
输出同上。
STDIN(标准输入)做为输入源:
catabc-file|parallelecho
输出同上。
多输入源
GNUParallel支持通过命令行指定多个输入源,它会生成所有的组合:
parallelecho:::ABC:::DEF
输出:
AD
AE
AF
BD
BE
BF
CD
CE
CF
多个文件做为输入源:
parallel-aabc-file-adef-fileecho
输出同上。
STDIN(标准输入)可以做为输入源中的一个,使用“-”:
catabc-file|parallel-a--adef-fileecho
输出同上。
可以使用“::::”替代-a:
catabc-file|parallelecho::::-def-file
输出同上。
:::和::::可以混合使用:
parallelecho:::ABC::::def-file
输出同上。
适配参数
–xapply从每一个输入源取一个参数:
parallel--xapplyecho:::ABC:::DEF
输出:
AD
BE
CF
如果其中一个输入源的长度比较短,它的值会被重复:
parallel--xapplyecho:::ABCDE:::FG
输出:
AF
BG
CF
DG
EF
改变参数分隔符
GNUParallel可以指定分隔符替代:::或::::,当这两个符号被其它命令占用的时候会特别有用:
parallel--arg-sep,,echo,,ABC::::def-file
输出:
AD
AE
AF
BD
BE
BF
CD
CE
CF
改变参数分隔符:
parallel--arg-file-sep//echo:::ABC//def-file
输出同上。
改变参数定界符
GNUParallel默认把一行做为一个参数:使用\n做为参数定界符。可以使用-d改变:
parallel-d_echo::::abc_-file
输出:
A
B
C
\0代表NULL:
parallel-d'\0'echo::::abc0-file
输出同上。
-0是-d'\0'的简写(通常用于从find…-print0读取输入):
parallel-0echo::::abc0-file
输出同上。
输入源中的结束值
GNUParallel支持指定一个值做为结束标志:
parallel-Estopecho:::ABstopCD
输出:
A
B
跳过空行
使用–no-run-if-empty来跳过空行:
(echo1;echo;echo2)|parallel--no-run-if-emptyecho
输出:
1
2
构建命令行
没有指定命令意味着参数就是命令
如果parallel之后没有给定命令,那么这些参数会被当做命令:
parallel:::ls'echofoo'pwd
输出:
[当前文件列表] foo [当前工作目录的路径]
命令可以是一个脚本文件,一个二进制可执行文件或一个bash的函数(须用export-f导出函数):
#OnlyworksinBashandonlyif$SHELL=.../bash my_func(){ echoinmy_func$1 } export-fmy_func parallelmy_func:::123
输出:
inmy_func1
inmy_func2
inmy_func3
替换字符串
5种替换字符串
GNUParallel支持多种替换字符串。默认使用{}:
parallelecho:::A/B.C
输出:
A/B.C
指定{}:
parallelecho{}:::A/B.C
输出同上
去掉扩展名{.}:
parallelecho{.}:::A/B.C
输出
A/B
去掉路径{/}:
parallelecho{/}:::A/B.C
输出:
B.C
只保留路径{//}:
parallelecho{//}:::A/B.C
输出:
A
去掉路径和扩展名{/.}:
parallelecho{/.}:::A/B.C
输出:
B
输出任务编号:
parallelecho{#}:::A/B.C
输出:
1
2
3
改变替换字符串
使用-I改变替换字符串符号{}:
parallel-I,,echo,,:::A/B.C
输出:
A/B.C
–extensionreplace替换{.}:
parallel--extensionreplace,,echo,,:::A/B.C
输出:
A/B
–basenamereplace替换{/}:
parallel--basenamereplace,,echo,,:::A/B.C
输出:
B.C
–dirnamereplace替换{//}:
parallel--dirnamereplace,,echo,,:::A/B.C
输出:
A
–basenameextensionreplace替换{/.}:
parallel--basenameextensionreplace,,echo,,:::A/B.C
输出:
B
–seqreplace替换{#}:
parallel--seqreplace,,echo,,:::ABC
输出:
1
2
3
指定位置替换字符串
如果有多个输入源时,可以通过{编号}指定某一个输入源的参数:
parallelecho{1}and{2}:::AB:::CD
输出:
AandC
AandD
BandC
BandD
可以使用////.和.:改变指定替换字符串:
parallelecho/={1/}//={1//}/.={1/.}.={1.}:::A/B.CD/E.F
输出:
/=B.C//=A/.=B.=A/B
/=E.F//=D/.=E.=D/E
位置可以是负数,表示倒着数:
parallelecho1={1}2={2}3={3}-1={-1}-2={-2}-3={-3}:::AB:::CD:::EF
输出:
1=A2=C3=E-1=E-2=C-3=A
1=A2=C3=F-1=F-2=C-3=A
1=A2=D3=E-1=E-2=D-3=A
1=A2=D3=F-1=F-2=D-3=A
1=B2=C3=E-1=E-2=C-3=B
1=B2=C3=F-1=F-2=C-3=B
1=B2=D3=E-1=E-2=D-3=B
1=B2=D3=F-1=F-2=D-3=B
按列输入
使用–colsep把文件中的行切分为列,做为输入参数。下面使用TAB(\t):
1=f12=f2
1=A2=B
1=C2=D
指定参数名
使用–header把每一行输入中的第一个值做为参数名:
parallel--header:echof1={f1}f2={f2}:::f1AB:::f2CD
输出:
f1=Af2=C
f1=Af2=D
f1=Bf2=C
f1=Bf2=D
使用–colsep处理使用TAB做为分隔符的文件:
parallel--header:--colsep'\t'echof1={f1}f2={f2}::::tsv-file.tsv
输出:
f1=Af2=B
f1=Cf2=D
多参数
–xargs让GNUParallel支持一行多个参数(可以指定上限):
catnum30000|parallel--xargsecho|wc-l
输出:
2
30000个参数被分为两行。
一行中的参数个数的上限通过-s指定。下面指定最大长度是10000,会被分为17行:
catnum30000|parallel--xargs-s10000echo|wc-l
为了获得更好的并发性,GNUParallel会在文件读取结束后再分发参数。
GNUParallel在读取完最后一个参数之后,才开始第二个任务,此时会把所有的参数平均分配到4个任务(如果指定了4个任务)。
第一个任务与上面使用–xargs的例子一样,但是第二个任务会被平均的分成4个任务,最终一共5个任务。
catnum30000|parallel--jobs4-mecho|wc-l
输出:
5
10分参数分配到4个任务可以看得更清晰:
parallel--jobs4-mecho:::{1..10}
输出:
123
456
789
10
替换字符串可以是单词的一部分。通过下面两个命令体会-m和-X的区别:
parallel--jobs4-mechopre-{}-post:::ABCDEFG
输出:
pre-AB-post
pre-CD-post
pre-EF-post
pre-G-post
-X与-m相反:
parallel--jobs4-Xechopre-{}-post:::ABCDEFG
输出:
pre-A-postpre-B-post
pre-C-postpre-D-post
pre-E-postpre-F-post
pre-G-post
使用-N限制每行参数的个数:
parallel-N3echo:::ABCDEFGH
输出:
ABC
DEF
GH
-N也可以用于指定位置替换字符串:
parallel-N3echo1={1}2={2}3={3}:::ABCDEFGH
输出:
1=A2=B3=C
1=D2=E3=F
1=G2=H3=
-N0只读取一个参数,但不附加:
parallel-N0echofoo:::123
输出:
foo
foo
foo
引用
如果命令行中包含特殊字符,就需要使用引号保护起来。
perl脚本'print“@ARGV\n”'与linux的echo的功能一样。
perl-e'print"@ARGV\n"'A
输出:
A
使用GNUParallel运行这条命令的时候,perl命令需要用引号包起来:
parallelperl-e'print"@ARGV\n"':::Thiswontwork
输出:
[Nothing]
使用-q保护perl命令:
parallel-qperl-e'print"@ARGV\n"':::Thisworks
输出:
This
works
也可以使用':
parallelperl-e\''print"@ARGV\n"'\':::Thisworks,too
输出:
This
works,
too
使用-quote:
parallel--shellquote parallel:Warning:Inputisreadfromtheterminal.Onlyexpertsdothisonpurpose.PressCTRL-Dtoexit. perl-e'print"@ARGV\n"' [CTRL-D]
输出:
perl\-e\\'print\\"@ARGV\\n\"\'
也可以使用命令:
parallelperl\-e\\'print\\"@ARGV\\n\"\':::Thisalsoworks
输出:
This
also
works
去除空格
使用–trim去除参数两头的空格:
parallel--trimrechopre-{}-post:::'A'
输出:
pre-A-post
删除左边的空格:
parallel--trimlechopre-{}-post:::'A'
输出:
pre-A-post
删除两边的空格:
parallel--trimlrechopre-{}-post:::'A'
输出:
pre-A-post
控制输出
以参数做为输出前缀:
parallel--tagechofoo-{}:::ABC
输出:
A foo-A
B foo-B
C foo-C
修改输出前缀–tagstring:
parallel--tagstring{}-barechofoo-{}:::ABC
输出:
A-bar foo-A
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。