
나는 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
테이블은이 스택 오버플로 답변(어디서 얻었어.배쉬 해커 위키) 다양한 Bash 변수가 어떻게 확장되는지 설명합니다.
python -i -c "from $@"
로 바뀌는 를 수행하고 python -i -c "from sys" "import" "stdout"
있으며 -c
단일 인수만 취하므로 명령을 실행하고 있습니다 from sys
. $*
로 확장되는 을(를) 사용하려고 합니다 python -i -c "from sys import stdout"
( $IFS
이 설정되지 않거나 공백으로 시작한다고 가정).
답변2
strace
, 언제나처럼 무슨 일이 일어나고 있는지 보여줍니다.
bash-4.1$ echo $$
3458
strace bash ...
그리고 다른 곳에서는(또는 함수 호출 방법을 알아낼 수도 있습니다 ):
bash-4.1$ strace -ff -o blah -p 3458
그리고 첫 번째 셸로 돌아갑니다.
bash-4.1$ from sys import stdout
File "<string>", line 1
from sys
^
SyntaxError: invalid syntax
>>>
bash-4.1$
그런 다음 다시 셸로 돌아갑니다 strace
.
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
인수는 확장 방법 또는 barfs가 잘린 명령 -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"에서 작동합니다.