Como disponibilizar uma função para o comando 'parallel' (GNU)?

6

No Bash, vamos considerar uma função que não faz nada além de echo do argumento seguido por "é um inteiro".

f () { num="${!1}"; echo $num is an integer; }
number=12
f number
# 12 is an integer

Eu gostaria de escrever em um arquivo um número de comandos que usa a função f e depois executar esses comandos em paralelo usando a função 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

Com source tudo funciona bem

source Commands.txt
1 is an integer
2 is an integer
3 is an integer
4 is an integer
5 is an integer

No entanto, quando tento executar os comandos em paralelo, ele retorna que a função f não foi encontrada

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

Existe uma maneira de tornar minha função f disponível para parallel sem ter que definir a função em cada linha do arquivo Commands.txt ?

    
por Remi.b 20.03.2016 / 22:06

2 respostas

5

Você basicamente tem três opções:

  1. export -f (que é um recurso bash não POSIX)
  2. Executa um shell que define a função em cada chamada
  3. Mova a função para um script de shell e execute essa alternativa

A opção 1 é provavelmente a mais fácil de demonstrar, então mostrarei essa:

$ 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

Observe que sua população de Commands.txt provavelmente está com erro, você precisa de f "$number" em Commands.txt para passar o número, não f number que passaria a string literal "number". Seu script deve gerar echo "number=$i; f \"\$number\"" (anote as fugas, que são importantes para evitar que $number seja interpretado em echo time, ou a " s que termina a string).

    
por 20.03.2016 / 22:16
2

O Bash pode exportar funções através de variáveis de ambiente.

export -f f

Note que este é um recurso bash, não disponível em outros shells da família sh.

Como alternativa, torne a função um script. Scripts e funções têm a mesma sintaxe além da linha de definição de função.

#!/bin/bash
num="${!1}"; echo $num is an integer;

Se você fizer isso, precisará exportar a variável que você passar para o script: as linhas em Command.txt precisarão parecer

export number=1; f number

ou

number=1 f number
    
por 20.03.2016 / 22:13