한 줄 명령 줄에서 여러 줄 문을 실행 하시겠습니까? 루프 전에 모듈을

-c1-liner 루프를 실행하기 위해 Python을 사용 하고 있습니다.

$ python -c "for r in range(10): print 'rob'"

이것은 잘 작동합니다. 그러나 for 루프 전에 모듈을 가져 오면 구문 오류가 발생합니다.

$ python -c "import sys; for r in range(10): print 'rob'"
  File "<string>", line 1
    import sys; for r in range(10): print 'rob'
              ^
SyntaxError: invalid syntax

이것이 어떻게 고칠 수 있는지 아십니까?

Makefile에 포함시킬 수 있도록 이것을 하나의 라이너로 만드는 것이 중요합니다.



답변

넌 할 수있어

echo -e "import sys\nfor r in range(10): print 'rob'" | python

또는 파이프없이 :

python -c "exec(\"import sys\nfor r in range(10): print 'rob'\")"

또는

(echo "import sys" ; echo "for r in range(10): print 'rob'") | python

또는 @ SilentGhost의 답변 / @Crast의 답변


답변

이 스타일은 메이크 파일에서도 사용할 수 있습니다 (실제로 자주 사용됨).

python - <<EOF
import sys
for r in range(3): print 'rob'
EOF

또는

python - <<-EOF
    import sys
    for r in range(3): print 'rob'
EOF

후자의 경우 선행 탭 문자 도 제거됩니다 (일부 구조화 된 전망을 달성 할 수 있음)

EOF 대신 행 시작 부분에 here 문서에 표시되지 않은 마커 단어를 표시 할 수 있습니다 (bash 맨 페이지 또는 here의 문서 참조 ).


답변

문제는 실제로 import 문과 관련이 없으며 for 루프 이전에 문제가 있습니다. 또는 더 구체적으로, 인라인 블록 앞에 나타나는 모든 것.

예를 들어, 다음은 모두 작동합니다.

python -c "import sys; print 'rob'"
python -c "import sys; sys.stdout.write('rob\n')"

수입품이 성명서 인 경우 문제가되지만 다음과 같이 작동하지는 않습니다.

python -c "__import__('sys'); for r in range(10): print 'rob'"

가장 기본적인 예를 들어, 다음과 같이 다시 작성할 수 있습니다.

python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"

그러나 람다는 명령문이나 여러 명령문이 아닌 표현식 만 실행할 수 있으므로 원하는 작업을 계속 수행하지 못할 수 있습니다. 그러나 생성자 표현식, 목록 이해, 람다, sys.stdout.write, “map”내장 및 일부 창의적인 문자열 보간 사이에 강력한 단일 라이너를 수행 할 수 있습니다.

문제는 얼마나 멀리 가고 싶고, 어떤 시점에서 .pymakefile이 실행 하는 작은 파일 을 작성하는 것이 낫지 않습니까?


답변


– 파이썬이 응답 작업을하려면 3.X을 뿐만 아니라, printA와 호출 기능 : 3.X에서, 단지 print('foo') 작동 2.X도 받아 반면 print 'foo'. -Windows
를 포함하는 크로스 플랫폼 관점 은 kxr의 유용한 답변을 참조하십시오 .

에서 bash, ksh또는zsh :

문자열이 전달되기 전에 실제 개행으로 확장되는 개행을 나타내는 데 사용할 수 있는 ANSI C 인용 문자열 ( $'...')을 사용 \n하십시오 python.

python -c $'import sys\nfor r in range(10): print("rob")'

노트 \n사이 importfor줄 바꿈에 영향을하기 위해 문을.

쉘 변수 값 을 이러한 명령에 전달 하려면 인수 를 사용 sys.argv하여 Python 스크립트 내에서 액세스하는 것이 가장 안전합니다 .

name='rob' # value to pass to the Python script
python -c $'import sys\nfor r in range(10): print(sys.argv[1])' "$name"

포함 된 쉘 변수 참조 와 함께 (이스케이프 시퀀스 사전 처리 된) 큰 따옴표로 묶인 명령 문자열 을 사용하는 장단점에 대한 설명은 아래를 참조하십시오.

$'...'문자열을 안전하게 사용하려면 :

  • 원래 소스 코드 \에서 더블 인스턴스 .

    • \<char>서열 – 등 \n이 경우에, 또한 예컨대 보통 용의자 \t, \r, \b-로 확장된다 $'...'(참조 : man printf지원 탈출을위한)
  • '인스턴스를 이스케이프 합니다 \'.

POSIX 호환 상태를 유지해야하는 경우 :

명령 대체printf 와 함께 사용 :

python -c "$(printf %b 'import sys\nfor r in range(10): print("rob")')"

이 유형의 문자열로 안전하게 작업하려면 :

  • 원래 소스 코드 \에서 더블 인스턴스 .

    • \<char>같은 – 시퀀스 \n이 경우에는, 그러나 또한이 같은 보통의 용의자 \t, \r, \b-에 의해 확장된다 printf(참조 man printf지원되는 이스케이프 시퀀스).
  • 패스 단일 인용 에 문자열 printf %b같은 임베디드 작은 따옴표 탈출 '\'' (원문 참조).

    • 작은 따옴표를 사용하면 이 문자열 내용을 해석하지 못하도록 보호합니다 .

      • 즉, 짧은 파이썬 스크립트 (이 경우와 같이)의 경우에는 큰 함정 문자열을 사용하여 변수 값을 스크립트 에 통합 할 수 있습니다 . 예를 들어, 쉘 $HOME은 현재 사용자의 홈 디렉토리로 확장 됩니다. 다음 명령에서 :

        • python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
      • 그러나 일반적으로 선호되는 접근 방식은 arguments 를 통해 쉘에서 값을 전달 sys.argv하고 Python을 통해 값 에 액세스하는 것입니다 . 위의 명령과 동일합니다 :

        • python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
    • 큰 따옴표로 묶인 문자열을 사용하는 것이 더 편리 하지만 포함되지 않은 작은 따옴표를 이스케이프 처리하지 않고 포함 된 큰 따옴표로 사용할 수 있습니다. \"또한 문자열 의 의도 에 따라 에서 해석 될 수도 있습니다. 소스 코드에서 쉘 $용이 `아닌 문자는 구문 오류를 유발하거나 문자열을 예기치 않게 변경할 수 있습니다.

      • 또한 \큰 따옴표로 묶인 셸에서 셸 자체 처리가 방해 될 수 있습니다. 예를 들어, 파이썬 이 리터럴 출력을 생성하게 ro\b하려면 전달 ro\\b해야합니다. 로모그래퍼 '...'쉘 문자열과 두 배로 \ 경우, 우리는 얻을 :
        python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
        반면에,이 수행 되지 로모그래퍼 의도 한대로 작업을 "..."쉘 문자열 :
        python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs'
        쉘 해석 모두 "\b""\\b"문자 등의 \b추가의 현기증 번호 요구, \원하는 효과를 달성하기 위해 인스턴스를 :
        python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"

하기 를 통해 코드를 전달stdin 보다는 -c:

참고 : 여기서는 단일 회선 솔루션 에 중점을두고 있습니다. xorho의 답변 은 여러 줄로 된 here-document 를 사용하는 방법을 보여줍니다 . 그러나 구분 기호 를 인용 하십시오. 예를 들어, <<'EOF'쉘에서 명시 적으로 문자열을 확장하지 않으려는 경우 (위의 경고와 함께 제공)


에서 bash, ksh또는zsh :

결합 ANSI C-인용 문자열을 ( $'...'로모그래퍼) 여기에 문자열 ( <<<...) :

python - <<<$'import sys\nfor r in range(10): print("rob")'

-pythonstdin (기본적으로 수행)에서 읽도록 명시 적으로 지시 합니다.
-이 경우 선택 사항이지만 스크립트에 인수 를 전달 하려면 스크립트 파일 이름에서 인수를 명확하게 지정해야합니다.

python - 'rob' <<<$'import sys\nfor r in range(10): print(sys.argv[1])'

POSIX 호환 상태를 유지해야하는 경우 :

stdin을 통해 출력을 전달하기 위해 파이프 라인printf 과 함께 위와 같이 사용하십시오 .

printf %b 'import sys\nfor r in range(10): print("rob")' | python

논쟁과 함께 :

printf %b 'import sys\nfor r in range(10): print(sys.argv[1])' | python - 'rob'

답변

이것이 어떻게 고칠 수 있는지 아십니까?

으로 구분 된 Python 문 ;은 “단일 문”일 수 있다는 사실에 의해 문제가 발생 합니다. 파이썬 문서 의 문법 파일에서 :

stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
             import_stmt | global_stmt | nonlocal_stmt | assert_stmt)

복합 명령문은 세미콜론을 통해 다른 명령문과 같은 행에 포함될 수 없으므로 -c플래그로 이를 수행하는 것은 매우 불편합니다.

bash 쉘 환경에서 파이썬을 시연 할 때 복합 문장을 포함시키는 것이 매우 유용하다는 것을 알았습니다. 이것을 확실하게 수행하는 유일한 간단한 방법은 heredocs (posix shell 일)를 사용하는 것입니다.

Heredocs

용도 히어 닥 (로 만든 <<)과 파이썬의 명령 줄 인터페이스 옵션을 , -:

$ python - <<-"EOF"
        import sys                    # 1 tab indent
        for r in range(10):           # 1 tab indent
            print('rob')              # 1 tab indent and 4 spaces
EOF

-<<( <<-)를 추가하면 을 사용 하여 들여 쓸 수 있습니다 (Stackoverflow는 탭을 공백으로 변환하므로 이것을 강조하기 위해 8 칸을 들여 쓰기했습니다). 선행 탭이 제거됩니다.

탭없이 다음과 같이 할 수 있습니다 <<.

$ python - << "EOF"
import sys
for r in range(10):
    print('rob')
EOF

인용 부호를 넣으면 매개 변수산술 확장이EOF 방지 됩니다 . 이것은 heredoc을 더 강력하게 만듭니다.

배쉬 여러 줄 문자열

큰 따옴표를 사용하면 셸 확장이 나타납니다.

$ python -c "
> import sys
> for p in '$PATH'.split(':'):
>     print(p)
> "
/usr/sbin
/usr/bin
/sbin
/bin
...

쉘 확장을 피하려면 작은 따옴표를 사용하십시오.

$ python -c '
> import sys
> for p in "$PATH".split(":"):
>     print(p)
> '
$PATH

파이썬에서 리터럴에서 따옴표 문자를 교체해야합니다. 기본적으로 BASH가 해석하는 따옴표 문자는 사용할 수 없습니다. 우리는 파이썬에서와 같이 그것들을 대체 할 수 있습니다. 그러나 이것은 이미 혼란스러워 보입니다. 그래서 나는 이것을 권장하지 않습니다 :

$ python -c '
import sys
for p in "'"$PATH"'".split(":"):
    print(p)
'
/usr/sbin
/usr/bin
/sbin
/bin
...

허용 된 답변 (및 기타)에 대한 비판

이것은 읽기 쉽지 않습니다 :

echo -e "import sys\nfor r in range(10): print 'rob'" | python

읽기가 어렵고 오류가 발생한 경우 디버깅하기가 추가로 어렵습니다.

python -c "exec(\"import sys\\nfor r in range(10): print 'rob'\")"

아마도 좀 더 읽기 쉽지만 여전히 추한 것입니다.

(echo "import sys" ; echo "for r in range(10): print 'rob'") | python

"파이썬에 있으면 나쁜 시간을 보낼 것입니다 .

$ python -c "import sys
> for r in range(10): print 'rob'"

mapfor-loops를 얻기 위해 이해를 남용 하거나 나열 하지 마십시오 .

python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"

이것들은 모두 슬프고 나쁘다. 하지 마십시오.


답변

return을 사용하고 다음 줄에 입력하십시오.

user@host:~$ python -c "import sys
> for r in range(10): print 'rob'"
rob
rob
...

답변

$ python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

잘 작동합니다. “[]”를 사용하여 for 루프를 인라인하십시오.