dotfn(){ . /dev/fd/0
} <<IN
$(printf '\n%s(){ "$@" '"'\n" "$2"
sed -e"/$2.*{/,\$!d;s/^/ /"\
-e"/^. *} *$/q;s/'/'"'\\&&/g' <"$1"
printf "\n';}")
IN
obviously it's not fool proof, but it scans a file named in its first argument for the first series of input that begins with its second arg followed at some point on the same line with a {
and pulls in all following lines until it encounters one which only matches blank space and a single }
.
while sed
does so it escapes all hard-quotes in input, and printf
wraps the input in two hard-quotes and also prepends it with the string "$@"
. it sticks all of this in a function named for your second argument. here's an example:
printf '
some_fn(){
echo some stuff
cat </dev/null
}
another_fn(){
for f in file*; do printf '\''%s\n'\'' "$f"; done
}
' >fn_file
i put those two functions in fn_file
, and then...
dotfn fn_file another_fn
...nothing happened. but...
another_fn printf %s\\n
another_fn(){
for f in file*; do printf '%s\n' "$f"; done
}
i enclosed the function within one named for itself, and i can inspect it with printf
or whatever, or i can redefine it:
another_fn eval; another_fn
file
file1.tsv
file1.txt
file2.tsv
file2.txt
filea.xyz
fileb.xyz
I replaced the . /dev/fd/0
in dotfn()
with a simple cat
and went after some_fn()
:
dotfn fn_file some_fn
some_fn(){ "$@" '
some_fn(){
echo some stuff
cat </dev/null
}
';}
source
or.
(dot) and just executing a script is whether it is done in your original shell process or in a new (subshell) process. For permanently setting variables or other shell properties (likecd
) you need the first, which the answers address. If you only need to execute the commands you can pipe to a new shell likeawk '/select/,/lines/' script | sh
. – dave_thompson_085 18 hours ago