如何使函数可用于命令`parallel`(GNU)?

Rem*_*i.b 9 shell bash function parallelism

在 Bash 中,让我们考虑一个函数,它除了echo后跟“是一个整数”的参数之外什么都不做。

f () { num="${!1}"; echo $num is an integer; }
number=12
f number
# 12 is an integer
Run Code Online (Sandbox Code Playgroud)

我想在一个文件上写一些使用该函数的命令,f然后使用该函数parallel(GNU)并行运行这些命令。

# Write Commands to the file `Commands.txt`
rm Commands.txt
touch Commands.txt
for i in $(seq 1 5)
do
   echo "number=$i; f number" >> Commands.txt
done
Run Code Online (Sandbox Code Playgroud)

随着source一切工作正常

source Commands.txt
1 is an integer
2 is an integer
3 is an integer
4 is an integer
5 is an integer
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试并行运行命令时,它返回f找不到该函数

parallel :::: Commands.txt
/bin/bash: f: command not found
/bin/bash: f: command not found
/bin/bash: f: command not found
/bin/bash: f: command not found
/bin/bash: f: command not found
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以使我的函数f可用而parallel无需在文件的每一行定义函数Commands.txt

Chr*_*own 6

你基本上有三个选择:

  1. export -f (这是一个非 POSIX bash 功能)
  2. 在每次调用时执行一个定义函数的 shell
  3. 将函数移动到 shell 脚本并运行它

选项 1 可能是最容易演示的,所以我将展示一个:

$ f() { num=$1; echo "$num is an integer"; }
$ export -f f
$ cat Commands.txt 
number=1; f "$number" 
number=2; f "$number" 
number=3; f "$number" 
number=4; f "$number" 
number=5; f "$number" 
$ parallel :::: Commands.txt
1 is an integer
2 is an integer
3 is an integer
4 is an integer
5 is an integer
Run Code Online (Sandbox Code Playgroud)

请注意,您的人口Commands.txt很可能在错误,您需要f "$number"Commands.txt通过数量,而不是f number它会通过文字串“数字”。生成它的脚本应该这样做echo "number=$i; f \"\$number\""(注意转义,这对于避免$numberecho时间被解释或"终止字符串很重要)。


Gil*_*il' 2

Bash 可以通过环境变量导出函数。

export -f f
Run Code Online (Sandbox Code Playgroud)

请注意,这是一个 bash 功能,在 sh 系列的其他 shell 中不可用。

或者,将该函数设为脚本。除了函数定义行之外,脚本和函数具有相同的语法。

#!/bin/bash
num="${!1}"; echo $num is an integer;
Run Code Online (Sandbox Code Playgroud)

如果这样做,您需要导出传递给脚本的变量:其中的行Command.txt需要看起来像

export number=1; f number
Run Code Online (Sandbox Code Playgroud)

或者

number=1 f number
Run Code Online (Sandbox Code Playgroud)