linux 命令 -- parallel

# 可以使用conda 安装
# 设置别名
alias p='parallel'
alias pp='env_parallel'  # echo '. `which env_parallel.bash`' >> $HOME/.bashrc
# env_parallel 可以使用自定义的alias, function

::: 			后面接参数; 标识符:::可以用参数修改: --arg-sep ,,,
:::: 			后面接文件; --arg-file-sep
-a				接文件;等同::::
p -a a.txt -a b.txt echo   # -a 或者 :::: 文件读入
p echo :::: a.txt :::: b.txt

-d 				修改 参数定界符, 默认 \n
-E				指定值作为结束终止
-N  			每行传参的个数, 只传N-1个, 到第N个时,跳过; -N0:即跳过所有的参数
--xargs			会在一行中输入尽可能多的参数, 输入源较短的重复使用
-s				一行中参数上限
-xapply 		从每一个源获取一个参数(或文件一行)
--header  		把每一行输入中的第一个值做为参数名
--colsep		行切分成多列, {1} {2}...
				转义: \|  \\\t 
				首列设置为{1},并且可以用字符串处理: 例如{1/..}
-j/ --jobs  	并行任务数
-m   			表示每个job不重复输出“背景”(context: 出参数之外的内容)
-X   			与-m相反,会重复输出“背景文本”

-q  			保护后面的命令, 特殊字符不用转义

--trim  lr 		去除参数两头的空格,(不能去除tab,\n) ;r: right空, l:left空 lr:两端
--tmpdir/ --results   		都是保存文件,但是后者可以有结构的保存
--delay  		延迟每个任务启动时间		# --delay 2.5
--halt  		终止任务
--pipe    		该参数使得我们可以将输入(stdin)分为多块(block),然后分配给多个CPU
				--round-robin参数可以打印已生成的结果(乱序) (有点鸡肋, 特别是涉及到IO处理)
--block  		参数可以指定每个block的大小,默认1M
--no-run-if-empty 		跳过空行
--dryrun			打印命令
--verbose/ -v		先打印命令, 然后再运行
--ungroup			立即打印已完成的部分
--linebuffer  		同上, 但是输出不错乱
--keep-order/ -k    强制使输出与参数保持顺序 --keep-order/-k
--interactive		交互确认输出
--timeout          设置最大运行时间
parallel --timeout 4.5 sleep {}\; echo {} ::: 2 4 6 8     # 最长时间4.5s
parallel --timeout 200% sleep {}\; echo {} ::: 2.1 2.2 3 7 2.3  # 杀死运行时间超过中值200%的
--bar               显示进度条
# 字符串替换
{}			# 整体 	 -I 修改替换符
{/}			# 去路径	 --basenamereplace		
{.}			# 去扩展名	--extensionreplace 
{/.}		# 去路径,去扩展名	--basenameextensionreplace 
{//}		# 获取路径 	--dirnamereplace			
{#}			# 获取任务编号 	--seqreplace			
{%}			# 当前jobID

{..}        # 去两个扩展: --rpl '{..} s:\.[^.]+$::;s:\.[^.]+$::;'
{/..}       # 去路径去两个扩展: --rpl '{/..} s:.*/::;s:\.[^.]+$::;s:\.[^.]+$::;'

# 定义一个新的字符串替换方式:  --rpl
p --rpl '{..} s:\.[^.]+$::;s:\.[^.]+$::;' echo {/..}  ::: /path/to/foo.tar.gz
		# /path/to/foo   # 定义 {..} : 删除两个suffix
p --rpl '{/..} s:.*/::;s:\.[^.]+$::;s:\.[^.]+$::;'  zcat {} \| sed 's:^:{/..}\\t:'
## note: parallel中替换等操作不能用 | 会引起歧义; 例如s|\t| | 等

# 设置替换字符串
p --rpl '{%(.+?)} s/$$1$//;' echo {%.tar.gz}.zip ::: foo.tar.gz

# 在{= =}中使用perl 表达式; 
p echo '{= s:\.[^.]+$::;s:\.[^.]+$::; =}' ::: foo.tar.gz  # foo
# 也可以使用一些paralle的内置函数
total_jobs()	# 总任务数
p echo Job {#} of {= '$_=total_jobs()' =} ::: {1..5}
skip()			# 跳过job
p echo {= 'if($_==3) { skip() }' =} ::: {1..5}
--parens ,,,,   # 使用,,,, 替换默认的 {==}

----------------------------------------
  --rpl '{} '
  --rpl '{#} $_=$job->seq()'
  --rpl '{%} $_=$job->slot()'
  --rpl '{/} s:.*/::'
  --rpl '{//} $Global::use{"File::Basename"} ||=
           eval "use File::Basename; 1;"; $_ = dirname($_);'
  --rpl '{/.} s:.*/::; s:\.[^/.]+$::;'
  --rpl '{.} s:\.[^/.]+$::'
---------------------------------------
# 贪婪匹配与非贪婪匹配
s|.*\.||  # 贪婪匹配
s|.*?\.|| # 非贪婪匹配, 量词后面加 ? 量词: * ? + {M,N}

# dir/sub/file.ex1.ex2.ex3
--plus    # 获取更多的预设替换标志
{+/}      # 获取路径   与{//} 相同
{+.}      # 获取一个后缀
{+..}	  # 获取两个后缀
{+...} 	  # 获取三个后缀
{.}       # 去一个后缀
{..}      # 去两个后缀
{...}     # 去三个后缀
{/..}     # 去路径, 去两个后缀
{/...}    # 去路径, 去三个后缀
{##}      # 总任务数
#  以下所有的都是等价的: 
 {}
 {+/}/{/}
 {.}.{+.}
 {+/}/{/.}.{+.}
 {..}.{+..}
 {+/}/{/..}.{+..}
 {...}.{+...}
 {+/}/{/...}.{+...}
# parallel 是perl写的, 如果plus仍满足不了, 可以直接修改源代码设置自己常用的 vi `which parallel`

# 1. 删除 /之前的字符; 2. 删除.之后的字符
p echo ::: 1 2  ::: a b 	  # 两两组合
p echo :::: a.txt :::: b.txt
p --xapply echo {1} {1} and {2} ::: A B ::: C D  # 多次输入, 指定输入源
p --xapply diff ::: `l /path/to/one/` ::: `l /path/to/two/`  # 比较文件夹这内容的差别; 常用于copy的文件夹
p echo /={1/} //={1//} /.={1/.} .={1.} ::: A/B.C D/E.F  # 输入源中也可以字符串替换
p  echo 1={1} 2={2} 3={3} -1={-1} -2={-2} -3={-3} ::: A B ::: C D ::: E F # 位置可以是负数


# 类似bash的字符串处理
{:-str}			# var为空时则为sr
{:num}			# 截取num到$
{:num1:num2}	# 截取num1~num2
{#str}			# 以str开头,则删除str
{%str}			# 以str结尾,则删除str
{/str1/str2}	# 用str2替换str1
{^str}			# 将开头是小写的单个字母str,改成大写
{^^str}			# 将单个小写的字母改成大写
{,str}			# 将开头是大写的单个字母str,改成小写
{,,str}			# 将单个大写的字母改成小写
## demo: 
unset var
echo ${var:-myval}					# myval
p --plus echo {:-myval} ::: "$var"
var=abcAaAdef
echo ${var:2}						# cAaAdef
p --plus echo {:2} ::: "$var"
echo ${var:2:3}						# cAa
p --plus echo {:2:3} ::: "$var"
echo ${var#bc}						# abcAaAdef
p --plus echo {#bc} ::: "$var"
echo ${var#abc}						# AaAdef
p --plus echo {#abc} ::: "$var"
echo ${var%de}						# abcAaAdef
p --plus echo {%de} ::: "$var"
echo ${var%def}						# abcAaA
p --plus echo {%def} ::: "$var"
echo ${var/def/ghi}					# abcAaAghi
p --plus echo {/def/ghi} ::: "$var"
echo ${var^a}						# AbcAaAdef
p --plus echo {^a} ::: "$var"
echo ${var^^a}						# AbcAAAdef
p --plus echo {^^a} ::: "$var"
var=AbcAaAdef
echo ${var,A}						# abcAaAdef
p --plus echo '{,A}' ::: "$var"
echo ${var,,A}						# abcaaadef
p --plus echo '{,,A}' ::: "$var"
 

p --xapply echo ::: 1 2 3 ::: a b c d f   # 较短的重复使用
p -k --arg-sep ,,, echo ,,, a b ,,, c d  # 设置参数分隔符
p --xapply --header : echo f1={f1} f2={f2} ::: f1 A B ::: f2 C D  # 将第一个值指定header
# -m(背景不重复) -X(背景重复)的使用; 一般需要配合-j参数
p --jobs 4 -m echo pre-{}-post ::: A B C D E F G
p --jobs 4 -X echo pre-{}-post ::: A B C D E F G
# -N  限制传入参数的个数
parallel -N3 echo ::: A B C D E F G H
# -N 可以设置位置替换
p -N4 echo 1={1} 2={2} 3={3} ::: A B C D E F G H
p -N0 echo foo ::: 1 2 3  # 只输出foo
# -q
p -q perl -e 'print "@ARGV\n"' ::: This works
#
p -j2 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1
p -j2 --ungroup 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1
p -j2 --linebuffer 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1
p -j2 -k 'printf "%s-start\n%s" {} {};sleep {};printf "%s\n" -middle;echo {}-end' ::: 4 2 1
p -j 2 echo {%} ::: A B C

# 使用函数
  my_func() {
    echo in my_func $1
  }
  export -f my_func      # 将my_func的函数名设置为变量名称
  p my_func ::: 1 2 3
 

note:

官方文档: https://www.gnu.org/software/parallel/parallel_tutorial.html#GNU-Parallel-Tutorial

你可能感兴趣的:(shell,linux,并行计算)