我想编写一个小 bash 函数,以便我可以告诉 bash,import os
或者from sys import stdout
它会生成一个新的 Python 解释器并导入模块。
后一个from
函数如下所示:
from () {
echo "from $@" | xxd
python3 -i -c "from $@"
}
如果我这样称呼:
$ from sys import stdout
00000000: 6672 6f6d 2073 7973 2069 6d70 6f72 7420 from sys import
00000010: 7374 646f 7574 0a stdout.
File "<string>", line 1
from sys
^
SyntaxError: invalid syntax
>>>
中的字节from sys
是
66 72 6f 6d 20 73 79 73 20
f r o m s y s
其中没有 EOF,但 Python 解释器的行为就好像它读取了 EOF。流末尾有一个换行符,这是预料之中的。
from
的姐妹,导入整个Python模块,看起来像这样,它通过清理和处理字符串以及在不存在的模块上失败来解决问题。
import () {
ARGS=$@
ARGS=$(python3 -c "import re;print(', '.join(re.findall(r'([\w]+)[\s|,]*', '$ARGS')))")
echo -ne '\0x04' | python3 -i
python3 -c "import $ARGS" &> /dev/null
if [ $? != 0 ]; then
echo "sorry, junk module in list"
else
echo "imported $ARGS"
python3 -i -c "import $ARGS"
fi
}
这解决了流中无法解释的 EOF 的问题,但我想了解为什么 Python 认为存在 EOF。
答案1
答案2
strace
一如既往,将显示正在发生的事情:
bash-4.1$ echo $$
3458
并且,在其他地方(或者您可以弄清楚如何strace bash ...
调用函数):
bash-4.1$ strace -ff -o blah -p 3458
回到第一个 shell:
bash-4.1$ from sys import stdout
File "<string>", line 1
from sys
^
SyntaxError: invalid syntax
>>>
bash-4.1$
然后回到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
因此,实际的-c
争论是-c "from sys"
因为如何"$@"
扩展,或者是一个被截断的命令python
。
答案3
$@
双引号中扩展为元素列表"$1" "$2" "$3"
等。
#!/bin/bash
expand () {
for string in "from $@" ; do
echo "$string"
done
}
expand sys import stdout
Python 期望代码位于一个参数中,而不是一系列参数中。
答案4
Strace 确实显示了所使用的参数。但查看正在处理的内容的最简单方法是printf '<%s> '
在每个相关行之前添加一个,并添加一个结束符echo
(以生成新行):
因此,该函数可以更改为:
from () {
printf '<%s> ' "from $@"; echo
printf '<%s> ' python3 -i -c "from $@"; echo
}
当被调用时:
$ from sys import stdout
<from sys> <import> <stdout>
<python3> <-i> <-c> <from sys> <import> <stdout>
很明显,“from sys”作为一个参数被发送到 python。
这就是 python 接收的内容,并且 python 作用于“from sys”。