Why is there an EOF in the middle of the arguments?
The table in this Stack Overflow answer (which got it from the Bash Hackers Wiki) explains how the different Bash variables are expanded:
You're doing python -i -c "from $@"
, which turns into python -i -c "from sys" "import" "stdout"
, and -c
only takes a single argument, so it's running the command from sys
. You want to use $*
, which will expand into python -i -c "from sys import stdout"
(assuming $IFS
is unset or starts with a space).
strace
, as always, will show what is going on:
bash-4.1$ echo $$
3458
And, elsewhere (or you could figure out how to strace bash ...
the function call):
bash-4.1$ strace -ff -o blah -p 3458
And back in that first shell:
bash-4.1$ from sys import stdout
File "<string>", line 1
from sys
^
SyntaxError: invalid syntax
>>>
bash-4.1$
And then back in the strace
shell:
Process 3458 attached
Process 25224 attached
^CProcess 3458 detached
bash-4.1$ grep exec blah.*
blah.25224:execve("/usr/bin/python", ["python", "-i", "-c", "from sys", "import", "stdout"], [/* 54 vars */]) = 0
Thus, the actual -c
argument is -c "from sys"
because of how "$@"
is expanded, or a truncated command that python
barfs on.
$@
in double quotes expands to a list of elements "$1" "$2" "$3"
etc.
#!/bin/bash
expand () {
for string in "from $@" ; do
echo "$string"
done
}
expand sys import stdout
Python expects the code to be in one argument, not a series of arguments.