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
}
';}