논쟁의 중간에 왜 EOF가 있습니까?


20

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가 없지만 파이썬 인터프리터는 마치 EOF를 읽는 것처럼 동작합니다. 스트림 끝에 줄 바꿈이 있으며 예상됩니다.

from전체 파이썬 모듈을 가져 오는 자매는 다음과 같이 보이고 문자열을 위생 처리하고 처리하고 존재하지 않는 모듈에서 실패하여 문제를 해결합니다.

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 문제를 해결하지만 파이썬이 EOF가 있다고 생각하는 이유를 이해하고 싶습니다.

답변:


42

이 스택 오버플로 답변 의 표 ( Bash Hackers Wiki 에서 가져온 표 )는 다양한 Bash 변수가 어떻게 확장되는지 설명합니다.

당신이하고있는 python -i -c "from $@"로 변신하는 python -i -c "from sys" "import" "stdout", 그리고 -c그 명령을 실행 그래서 단지 하나의 인자를 from sys. 을 사용하려고합니다.로 $*확장됩니다 python -i -c "from sys import stdout"( $IFS설정 되어 있지 않거나 공백으로 시작 한다고 가정 ).


2
이 가치있는 정보 : 한, 삭제 취소 주셔서 감사합니다
고양이

1
이것이 실제로 문제를 해결하기 때문에 이것이 받아 들여지는 대답이라고 생각합니다. 다른 반대 의견을 가진 사람은 단지 문제를 설명하지만 해결책이나 대안을 제시하지는 않습니다.
Ferrybig

좋은 대답입니다. 이 테이블은 실제로 Bash Hackers Wiki에서 나왔습니다. 적절한 속성을 추가하고 배포 할 권한이 있는지 확인할 수 있습니까?
Monica와의 가벼움 경주

22

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인수는 확장 -c "from sys"방법 "$@"또는 pythonbarfs 가 잘리는 명령 때문 입니다.


9

$@큰 따옴표로 묶으면 요소 목록 "$1" "$2" "$3"등으로 확장됩니다 .

#!/bin/bash
expand () {
    for string in "from $@" ; do
        echo "$string"
    done
}

expand sys import stdout

파이썬은 코드가 일련의 인수가 아닌 하나의 인수에있을 것으로 예상합니다.


6

파이썬은 다음과 같이 호출됩니다

execve("/usr/bin/python", ["python", "-i", "-c", "from sys", "import", "stdout"], [/* 54 vars */])

( 교감의 답변 참조 ).

$@단일 문자열로 확장 하려면 (sane 가정 $IFS) $*큰 따옴표 안에 사용할 수 있습니다 .

python3 -i -c "from $*"

확인 strace -e execve:

execve("/usr/bin/python", ["python", "-i", "-c", "from sys import stdout"], [/* 54 vars */]) = 0

2

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"가 하나의 인수로 파이썬에 전송되고 있음이 분명합니다.
그것은 파이썬이받는 것입니다. 그리고 파이썬은 "sys로부터"에 작용합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.