논쟁 중간에 EOF가 있는 이유는 무엇입니까?

논쟁 중간에 EOF가 있는 이유는 무엇입니까?

나는 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"에서 작동합니다.

관련 정보