Fonte apenas parte de um script de outro script?

2

Isso provavelmente nunca seria a melhor abordagem para algo, mas eu estou querendo saber se é possível.

Algo como:

awk '/function_i_want_to_call/,/^$/{print}' script_containing_function | xargs source

function_i_want_to_call arg1 arg2 arg3

Exceto realmente trabalhando.

    
por Wildcard 13.11.2015 / 18:50

3 respostas

3

Primeiro, você precisa determinar rigorosamente qual comando produzirá a parte específica que deseja obter. Para um exemplo trivial, dado o arquivo

var1=value1
var2=value2

você pode definir apenas var1 usando head -n1 filename . Isso poderia ser um pipeline de complexidade arbitrária, se você quisesse.

Em seguida, execute:

source <( pipeline_of_arbitrary_complexity some_filename )

Funciona apenas em bash . Para fazer isso no POSIX, acho que você precisaria criar um arquivo temporário.

    
por 13.11.2015 / 18:58
3

No bash / ksh e similar, você pode usar <() para evitar a sub-lista que | cria:

insourcable.sh :

echo hallo welt
echo hello world
echo ahoj světe

Suponha que você queira apenas a linha número dois na origem:

. <( sed -n '2 p' < insourcable.sh )

(imprime "olá mundo")

    
por 13.11.2015 / 18:58
1
dotfn(){ . /dev/fd/0
} <<IN
        $(printf '\n%s(){ "$@" '"'\n" "$2"
          sed   -e"/$2.*{/,\$!d;s/^/    /"\
                -e"/^. *} *$/q;s/'/'"'\&&/g'  <"$1"
          printf "\n';}")
IN

obviamente, não é à prova de erros, mas examina um arquivo nomeado em seu primeiro argumento para a primeira série de entrada que começa com seu segundo argumento seguido em algum ponto na mesma linha com { e extrai todas as linhas seguintes até encontrar um que corresponda apenas ao espaço em branco e um único } .

enquanto sed faz isso, ele escapa de todas as aspas duras na entrada, e printf quebra a entrada em duas aspas duras e também o preende com a string "$@" . Ele cola tudo isso em uma função nomeada para seu segundo argumento. aqui está um exemplo:

printf '
some_fn(){
        echo some stuff
        cat </dev/null
}

another_fn(){
        for f in file*; do printf '\''%s\n'\'' "$f"; done
}
' >fn_file

eu coloco essas duas funções em fn_file , e então ...

dotfn fn_file another_fn

... nada aconteceu. mas ...

another_fn printf %s\n
another_fn(){
    for f in file*; do printf '%s\n' "$f"; done
}

eu coloquei a função dentro de um nome para si mesmo, e eu posso inspecioná-lo com printf ou qualquer outro, ou eu posso redefini-lo:

another_fn eval; another_fn
file
file1.tsv
file1.txt
file2.tsv
file2.txt
filea.xyz
fileb.xyz

Substitui o . /dev/fd/0 em dotfn() por um simples cat e fui atrás de some_fn() :

dotfn fn_file some_fn
some_fn(){ "$@" '
    some_fn(){
        echo some stuff
        cat </dev/null
    }

';}
    
por 13.11.2015 / 21:58