Thực hiện các câu lệnh nhiều dòng trong dòng lệnh một dòng?


197

Tôi đang sử dụng Python -cđể thực hiện một vòng lặp một lớp, tức là:

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

Điều này hoạt động tốt. Tuy nhiên, nếu tôi nhập mô-đun trước vòng lặp for, tôi sẽ gặp lỗi cú pháp:

$ 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

Bất kỳ ý tưởng làm thế nào điều này có thể được sửa chữa?

Điều quan trọng đối với tôi là có một lớp lót để tôi có thể đưa nó vào Makefile.


Điều này có trả lời câu hỏi của bạn không? Sử dụng từ điển để chọn chức năng thực thi
pfabri

Câu trả lời:


182

bạn có thể làm

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

hoặc đường ống w / out:

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

hoặc là

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

hoặc câu trả lời của @ SilentGhost / câu trả lời của @ Crast


Tùy chọn cuối cùng hoạt động tuyệt vời với python3 trong Windows
Ian Ellis

1
@RudolfOlah hy vọng bạn biết điều đó ngay bây giờ nhưng chỉ để tham khảo, bạn cần phải bọc câu lệnh in cho các phiên bản python3 + như:python -c "exec(\"import sys\nfor r in range(10): print('rob')\")"
systrigger

@systrigger cảm ơn, tôi đã bỏ lỡ rằng tôi nghĩ rằng tôi đang vội và không nhận ra rằng heh

89

kiểu này cũng có thể được sử dụng trong makefiles (và trên thực tế nó được sử dụng khá thường xuyên).

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

hoặc là

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

trong trường hợp sau, các ký tự tab dẫn đầu cũng bị loại bỏ (và một số triển vọng có cấu trúc có thể đạt được)

thay vì EOF có thể đứng bất kỳ từ đánh dấu nào không xuất hiện trong tài liệu ở đây ở đầu một dòng (xem thêm tài liệu ở đây trong trang bash hoặc tại đây ).


9
Đẹp. Để vượt qua các đối số , chỉ cần đặt chúng sau <<EOF. Tuy nhiên, lưu ý rằng tốt hơn là trích dẫn dấu phân cách - ví dụ: <<'EOF'để bảo vệ nội dung của tài liệu ở đây khỏi các mở rộng vỏ phía trước .
mkuity0

56

Vấn đề không thực sự xảy ra với câu lệnh nhập khẩu, đó là vấn đề xảy ra trước vòng lặp for. Hay cụ thể hơn, bất cứ điều gì xuất hiện trước một khối nội tuyến.

Ví dụ, tất cả đều hoạt động:

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

Nếu nhập khẩu là một tuyên bố là một vấn đề, điều này sẽ hoạt động, nhưng nó không:

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

Ví dụ rất cơ bản của bạn, bạn có thể viết lại như sau:

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

Tuy nhiên, lambdas chỉ có thể thực thi các biểu thức, không phải các câu lệnh hoặc nhiều câu lệnh, vì vậy bạn vẫn có thể không thể làm điều bạn muốn làm. Tuy nhiên, giữa các biểu thức trình tạo, hiểu danh sách, lambdas, sys.stdout.write, dựng sẵn "bản đồ" và một số phép nội suy chuỗi sáng tạo, bạn có thể thực hiện một số lớp lót mạnh mẽ.

Câu hỏi là, bạn muốn đi bao xa và vào thời điểm nào thì không tốt hơn để viết một .pytệp nhỏ mà tệp thực hiện của bạn thực hiện thay thế?


31


- Để làm cho câu trả lời này hoạt động với Python 3.x , printđược gọi là hàm : trong 3.x, chỉ print('foo') hoạt động, trong khi 2.x cũng chấp nhận print 'foo'.
- Để biết phối cảnh đa nền tảng bao gồm Windows , hãy xem câu trả lời hữu ích của kxr .

Trong bash, kshhoặczsh :

Sử dụng chuỗi trích dẫn ANSI C ( $'...'), cho phép sử dụng \nđể thể hiện các dòng mới được mở rộng thành các dòng mới thực tế trước khi chuỗi được chuyển đến python:

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

Lưu ý \ngiữa importvà các forcâu lệnh để thực hiện ngắt dòng.

Để truyền các giá trị biến shell cho một lệnh như vậy, an toàn nhất là sử dụng các đối số và truy cập chúng thông qua sys.argvbên trong tập lệnh Python:

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

Xem bên dưới để thảo luận về những ưu và nhược điểm của việc sử dụng chuỗi lệnh được trích dẫn kép (đã xử lý trước chuỗi) với các tham chiếu biến shell được nhúng .

Để làm việc an toàn với $'...'chuỗi:

  • Trường \ hợp kép trong mã nguồn ban đầu của bạn .
    • \<char>trình tự - ví dụ như \ntrong trường hợp này, mà còn là nghi phạm thông thường như \t, \r, \b- được mở rộng bằng $'...'(xem man printfcho thoát được hỗ trợ)
  • Thoát 'trường hợp như \'.

Nếu bạn phải duy trì tuân thủ POSIX :

Sử dụng printfvới lệnh thay thế :

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

Để làm việc an toàn với loại chuỗi này:

  • Trường \ hợp kép trong mã nguồn ban đầu của bạn .
    • \<char>trình tự - ví dụ như \ntrong trường hợp này, mà còn là nghi phạm thông thường như \t, \r, \b- được mở rộng bằng printf(xem man printfcho chuỗi thoát được hỗ trợ).
  • Truyền một chuỗi trích dẫn đơn đến printf %bthoát các dấu ngoặc đơn được nhúng dưới dạng '\'' (sic).

    • Sử dụng dấu ngoặc đơn bảo vệ nội dung của chuỗi khỏi sự giải thích của trình bao .

      • Điều đó nói rằng, đối với các tập lệnh Python ngắn (như trong trường hợp này), bạn có thể sử dụng chuỗi trích dẫn kép để kết hợp các giá trị biến shell vào tập lệnh của mình - miễn là bạn biết về những cạm bẫy liên quan (xem điểm tiếp theo); ví dụ: shell mở rộng $HOMEđến thư mục nhà hiện tại của người dùng. trong lệnh sau:

        • python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
      • Tuy nhiên, cách tiếp cận thường được ưa thích là chuyển các giá trị từ shell thông qua các đối số và truy cập chúng thông qua sys.argvPython; tương đương với lệnh trên là:

        • python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
    • Mặc dù sử dụng chuỗi trích dẫn kép sẽ thuận tiện hơn - nó cho phép bạn sử dụng các trích dẫn đơn được nhúng và trích dẫn kép được nhúng như \"- nó cũng làm cho chuỗi có thể được giải thích bởi trình bao , có thể có hoặc không có ý định; $và các `ký tự trong mã nguồn của bạn không dành cho shell có thể gây ra lỗi cú pháp hoặc thay đổi chuỗi bất ngờ.

      • Ngoài ra, quá trình \xử lý riêng của shell trong chuỗi trích dẫn kép có thể cản trở; ví dụ, để có được Python để tạo đầu ra theo nghĩa đen ro\b, bạn phải truyền ro\\bcho nó; với '...'chuỗi shell và các trường hợp nhân đôi \ , chúng tôi nhận được:
        python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
        Ngược lại, điều này không hoạt động như dự định với "..."chuỗi shell:
        python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs'
        Shell diễn giải cả hai "\b""\\b"theo nghĩa đen \b, đòi hỏi số lượng phiên bản bổ sung chóng mặt \để đạt được hiệu quả mong muốn:
        python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"

Để truyền mã quastdin chứ không phải -c:

Lưu ý: Tôi đang tập trung vào các giải pháp đơn tuyến tại đây; Câu trả lời của xorho cho thấy cách sử dụng tài liệu nhiều dòng ở đây - tuy nhiên hãy chắc chắn trích dẫn dấu phân cách; ví dụ, <<'EOF'trừ khi bạn rõ ràng muốn shell mở rộng chuỗi lên phía trước (đi kèm với các lưu ý ở trên).


Trong bash, kshhoặczsh :

Kết hợp một chuỗi trích dẫn ANSI C ( $'...') với một chuỗi ở đây ( <<<...):

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

-nói pythonrõ ràng để đọc từ stdin (mà nó làm theo mặc định). -là tùy chọn trong trường hợp này, nhưng nếu bạn cũng muốn truyền đối số cho tập lệnh, bạn cần nó để phân tán đối số từ tên tệp tập lệnh:

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

Nếu bạn phải duy trì tuân thủ POSIX :

Sử dụng printfnhư trên, nhưng với một đường ống để vượt qua đầu ra của nó thông qua stdin:

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

Với một đối số:

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

2
Đây phải là câu trả lời được bầu!
mắt

1
Điều này cũng hoạt động và có lẽ là câu trả lời tốt nhất vì nó bao gồm một lời giải thích đầy đủ, bravo!

22

Bất kỳ ý tưởng làm thế nào điều này có thể được sửa chữa?

Vấn đề của bạn được tạo ra bởi thực tế là các câu lệnh Python, được phân tách bằng ;, chỉ được phép là "các câu lệnh nhỏ", tất cả đều là một lớp. Từ tệp ngữ pháp trong tài liệu 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ác câu lệnh ghép không thể được đưa vào cùng dòng với các câu lệnh khác thông qua dấu chấm phẩy - vì vậy hãy thực hiện điều này với -c cờ trở nên rất bất tiện.

Khi trình diễn Python khi ở trong môi trường bash shell, tôi thấy rất hữu ích khi bao gồm các câu lệnh ghép. Cách đơn giản duy nhất để làm điều này một cách đáng tin cậy là với heredocs (một thứ vỏ posix).

Heredocs

Sử dụng một tùy chọn (được tạo bằng <<) và tùy chọn giao diện dòng lệnh của Python , -:

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

Thêm -sau <<(the <<-) cho phép bạn sử dụng các tab để thụt lề (Stackoverflow chuyển đổi các tab thành khoảng trắng, vì vậy tôi đã thụt 8 khoảng trắng để nhấn mạnh điều này). Các tab hàng đầu sẽ bị tước.

Bạn có thể làm điều đó mà không cần các tab chỉ với <<:

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

Đặt dấu ngoặc kép xung quanh EOFngăn chặn mở rộng tham sốsố học . Điều này làm cho các di truyền mạnh mẽ hơn.

Chuỗi đa dòng Bash

Nếu bạn sử dụng dấu ngoặc kép, bạn sẽ nhận được mở rộng shell:

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

Để tránh mở rộng vỏ, sử dụng dấu ngoặc đơn:

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

Lưu ý rằng chúng ta cần hoán đổi các ký tự trích dẫn trên các chữ trong Python - về cơ bản chúng ta không thể sử dụng ký tự trích dẫn đang được BASH diễn giải. Chúng ta có thể thay thế chúng mặc dù, giống như chúng ta có thể trong Python - nhưng điều này có vẻ khá khó hiểu, đó là lý do tại sao tôi không khuyên bạn điều này:

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

Phê bình câu trả lời được chấp nhận (và những người khác)

Điều này không dễ đọc lắm:

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

Không dễ đọc và cũng khó gỡ lỗi trong trường hợp có lỗi:

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

Có lẽ dễ đọc hơn một chút, nhưng vẫn khá xấu xí:

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

Bạn sẽ có một thời gian tồi tệ nếu bạn có "con trăn của bạn:

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

Đừng lạm dụng maphoặc liệt kê các hiểu biết để có được các vòng lặp:

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

Đây là tất cả buồn và xấu. Đừng làm chúng.


3
++ cho thông tin ngữ pháp; (không mở rộng) ở đây-doc là tiện ích và là giải pháp mạnh mẽ nhất, nhưng rõ ràng không phải là một lớp lót. Nếu một giải pháp một dòng là bắt buộc, sử dụng chuỗi trích dẫn ANSI C ( bash, kshhoặc zsh) là một giải pháp hợp lý: python -c $'import sys\nfor r in range(10): print(\'rob\')'(bạn sẽ chỉ phải lo lắng về việc thoát dấu ngoặc đơn (mà bạn có thể tránh bằng cách sử dụng dấu ngoặc kép) và dấu gạch chéo ngược).
mkuity0

14

chỉ cần sử dụng return và gõ nó vào dòng tiếp theo:

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

6
Nghiêm túc mà nói, bạn sẽ làm hỏng một cái gì đó nếu bạn tiếp tục làm điều này. python $(srcdir)/myscript.pycho công lý tuyệt vời.
Jason Orendorff

10

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

Hoạt động tốt. Sử dụng "[]" để nội tuyến vòng lặp for của bạn.


9

Vấn đề không nằm ở importtuyên bố. Vấn đề là các câu lệnh luồng điều khiển không hoạt động trong một lệnh python. Thay thế nóimport câu lệnh bằng bất kỳ câu lệnh nào khác và bạn sẽ thấy vấn đề tương tự.

Hãy suy nghĩ về nó: python không thể nội tuyến mọi thứ. Nó sử dụng thụt vào dòng điều khiển nhóm.


7

Nếu hệ thống của bạn tuân thủ Posix.2, nó sẽ cung cấp printftiện ích:

$ printf "print 'zap'\nfor r in range(3): print 'rob'" | python
zap
rob
rob
rob

2
Giải pháp tốt, nhưng tôi khuyên bạn nên sử dụng printf %b '...' | pythonđể tăng cường độ mạnh mẽ, bởi vì nó ngăn không cho printfdiễn giải các chuỗi như %d(định dạng định dạng) trong chuỗi đầu vào. Ngoài ra, trừ khi bạn rõ ràng muốn áp dụng mở rộng shell cho chuỗi lệnh Python của mình lên phía trước (có thể gây nhầm lẫn), tốt hơn là sử dụng '(trích dẫn đơn) cho trích dẫn bên ngoài, để tránh cả mở rộng và xử lý backlash mà shell áp dụng để chuỗi trích dẫn kép.
mkuity0 7/07/2016

5

single/double quotesbackslashở mọi nơi:

$ python -c 'exec("import sys\nfor i in range(10): print \"bob\"")'

Tốt hơn nhiều:

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

vì thế. nhiều tốt hơn.
Marc

4

(đã trả lời 23 tháng 11, 10 lúc 19:48) Tôi không thực sự là một Pythoner lớn - nhưng tôi đã tìm thấy cú pháp này một lần, quên từ đâu đến, vì vậy tôi nghĩ rằng tôi đã ghi lại nó:

nếu bạn sử dụng sys.stdout.writethay vì print( sự khác biệt, sys.stdout.writelấy các đối số làm hàm, trong ngoặc đơn - trong khi printkhông ), thì đối với một lớp lót, bạn có thể thoát khỏi việc đảo ngược thứ tự của lệnh và forxóa dấu chấm phẩy, và đặt lệnh trong dấu ngoặc vuông, nghĩa là:

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

Không biết cú pháp này sẽ được gọi như thế nào trong Python :)

Hi vọng điêu nay co ich,

Chúc mừng!


(EDIT Tue ngày 9 tháng 4 20:30:30 2013) Chà, tôi nghĩ rằng cuối cùng tôi đã tìm thấy những dấu ngoặc vuông này trong một lớp lót là gì; chúng là "danh sách hiểu" (rõ ràng); lưu ý đầu tiên này trong Python 2.7:

$ STR=abc
$ echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); print a"
<generator object <genexpr> at 0xb771461c>

Vì vậy, lệnh trong ngoặc tròn / dấu ngoặc đơn được xem như là một "đối tượng trình tạo"; nếu chúng ta "lặp lại" thông qua nó bằng cách gọi next()- thì lệnh bên trong dấu ngoặc đơn sẽ được thực thi (lưu ý "abc" trong đầu ra):

$ echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); a.next() ; print a"
abc
<generator object <genexpr> at 0xb777b734>

Nếu bây giờ chúng ta sử dụng dấu ngoặc vuông - lưu ý rằng chúng ta không cần gọi next()để thực thi lệnh, nó sẽ thực thi ngay khi được gán; tuy nhiên, kiểm tra sau đó cho thấy rằnga được None:

$ echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; print a"
abc
[None]

Điều này không để lại nhiều thông tin cần tìm, đối với trường hợp dấu ngoặc vuông - nhưng tôi tình cờ thấy trang này mà tôi nghĩ giải thích:

Mẹo và thủ thuật Python - Phiên bản đầu tiên - Hướng dẫn Python | Dream.In.Code :

Nếu bạn nhớ lại, định dạng chuẩn của trình tạo dòng đơn là một loại vòng lặp 'cho' trong dấu ngoặc. Điều này sẽ tạo ra một đối tượng lặp lại 'một lần bắn', đó là một đối tượng bạn có thể lặp đi lặp lại chỉ theo một hướng và bạn không thể sử dụng lại một khi bạn đạt đến điểm cuối.

Một "mức độ hiểu danh sách" trông gần giống như một trình tạo một dòng thông thường, ngoại trừ các dấu ngoặc thông thường - () - được thay thế bằng dấu ngoặc vuông - []. Ưu điểm chính của sự hiểu biết toàn diện là tạo ra một 'danh sách', chứ không phải là một đối tượng có thể lặp lại 'một lần bắn', để bạn có thể qua lại, thêm các yếu tố, sắp xếp, v.v.

Và thực sự nó là một danh sách - đó chỉ là yếu tố đầu tiên của nó trở thành không có gì ngay khi nó được thực thi:

$ echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin].__class__"
abc
<type 'list'>
$ echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin][0]"
abc
None

Việc hiểu danh sách được ghi lại trong 5. Cấu trúc dữ liệu: 5.1.4. Danh sách hiểu - Tài liệu Python v2.7.4 là " Hiểu danh sách cung cấp một cách ngắn gọn để tạo danh sách"; có lẽ, đó là nơi mà "khả năng thực thi" của các danh sách được phát huy trong một lớp lót.

Chà, hy vọng tôi không quá kinh khủng ở đây ...

EDIT2: và đây là dòng lệnh một lớp với hai vòng lặp không lồng nhau; cả hai được đặt trong dấu ngoặc vuông "hiểu danh sách":

$ echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; b=[sys.stdout.write(str(x)) for x in range(2)] ; print a ; print b"
abc
01[None]
[None, None]

Lưu ý rằng "danh sách" thứ hai bbây giờ có hai phần tử, vì vòng lặp for của nó được chạy rõ ràng hai lần; tuy nhiên, kết quả của sys.stdout.write()cả hai trường hợp là (rõ ràng) None.


4

Biến thể này có khả năng di động nhất để đưa các tập lệnh đa dòng lên dòng lệnh trên Windows và * nix, py2 / 3, không có đường ống:

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

(Không có ví dụ nào khác được thấy ở đây cho đến nay đã làm như vậy)

Không gọn gàng trên Windows là:

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

Neat trên bash / * nix là:

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

Hàm này biến bất kỳ tập lệnh đa dòng nào thành một lệnh di động một lệnh:

def py2cmdline(script):
    exs = 'exec(%r)' % re.sub('\r\n|\r', '\n', script.rstrip())
    print('python -c "%s"' % exs.replace('"', r'\"'))

Sử dụng:

>>> py2cmdline(getcliptext())
python -c "exec('print \'AA\tA\'\ntry:\n for i in 1, 2, 3:\n  print i / 0\nexcept:\n print \"\"\"longer\nmessage\"\"\"')"

Đầu vào là:

print 'AA   A'
try:
 for i in 1, 2, 3:
  print i / 0
except:
 print """longer
message"""

++ cho góc đa nền tảng và bộ chuyển đổi. Lệnh đầu tiên của bạn cũng tốt như về mặt tính di động (bỏ PowerShell sang một bên), nhưng cuối cùng không có cú pháp đa nền tảng duy nhất, hoàn toàn mạnh mẽ , bởi vì nhu cầu sử dụng dấu ngoặc kép sau đó có nguy cơ mở rộng vỏ không mong muốn, với Windows yêu cầu thoát các ký tự khác với các shell giống như POSIX. Trong PowerShell v3 trở lên, bạn có thể làm cho các dòng lệnh của mình hoạt động bằng cách chèn tùy chọn "dừng phân tích cú pháp" --%trước đối số chuỗi lệnh.
mkuity0 7/07/2016

@ mkuity0 " mở rộng vỏ không mong muốn ": tốt, việc chèn các mở rộng vỏ vào một cái gì đó như print "path is %%PATH%%"resp. print "path is $PATH"thường là tùy chọn mà một người muốn trong một tập lệnh hoặc dòng lệnh - trừ khi một người thoát khỏi mọi thứ như bình thường cho nền tảng. Tương tự với các ngôn ngữ khác. (Bản thân cú pháp Python không thường xuyên đề xuất sử dụng% và $ theo cách cạnh tranh.)
kxr

Nếu bạn chèn các tham chiếu biến shell trực tiếp vào mã nguồn Python, theo định nghĩa, nó sẽ không khả dụng. Quan điểm của tôi là ngay cả khi bạn thay vì xây dựng tài liệu tham khảo nền tảng cụ thể trong riêng các biến mà bạn vượt qua như các đối số một duy nhất, "vỏ miễn phí" Python lệnh, mà có thể không phải lúc nào công việc, bởi vì bạn không thể bảo vệ chuỗi dụng dấu ngoặc kép portably : ví dụ, nếu bạn cần bằng chữ $foo trong mã Python của bạn thì sao? Nếu bạn thoát nó vì \$foolợi ích của các vỏ giống như POSIX, cmd.exevẫn sẽ thấy thêm \ . Nó có thể là hiếm nhưng nó đáng để biết về.
mkuity0

Cố gắng thực hiện điều này trong Windows PowerShell, nhưng vấn đề là python -c exec ("" "..." "") không tạo ra bất kỳ đầu ra nào, bất kể mã trong ... có thể được thực thi không hay không; Tôi có thể đặt bất kỳ lời nói vô nghĩa nào ở đó, và kết quả sẽ giống nhau. Tôi cảm thấy như cái vỏ đang "ăn" cả hai dòng stdout và stderr - làm thế nào tôi có thể làm cho nó nhổ chúng ra?
Yury

2

Kịch bản lệnh này cung cấp giao diện dòng lệnh giống Perl:

Pyliner - Tập lệnh để chạy mã Python tùy ý trên dòng lệnh (công thức Python)


Tôi nghĩ rằng họ muốn một cái gì đó để khắc phục điều đó, không sử dụng một công cụ khác. Dù sao, gợi ý hay
enrico.bacis

Tôi đồng ý với @ enrico.bacis, nhưng tôi vẫn vui khi bạn thêm câu trả lời này. Nó trả lời câu hỏi tôi có khi tôi viết trang này.
tbc0

1

Khi tôi cần làm điều này, tôi sử dụng

python -c "$(echo -e "import sys\nsys.stdout.write('Hello World!\\\n')")"

Lưu ý dấu gạch chéo ba cho dòng mới trong câu lệnh sys.stdout.write.


Điều này hoạt động, nhưng vì bạn đang sử dụng echo -e, không đạt tiêu chuẩn và yêu cầu bash, kshhoặc zsh, bạn cũng có thể sử dụng một $'...'chuỗi trực tiếp, điều này cũng đơn giản hóa việc thoát:python -c $'import sys\nsys.stdout.write("Hello World!\\n")'
mkuity0

Câu trả lời này hoạt động, các câu trả lời khác không hoạt động cho Python3

1

Tôi muốn một giải pháp với các thuộc tính sau:

  1. Có thể đọc được
  2. Đọc stdin để xử lý đầu ra của các công cụ khác

Cả hai yêu cầu đều không được cung cấp trong các câu trả lời khác, vì vậy đây là cách đọc stdin trong khi thực hiện mọi thứ trên dòng lệnh:

grep special_string -r | sort | python3 <(cat <<EOF
import sys
for line in sys.stdin:
    tokens = line.split()
    if len(tokens) == 4:
        print("%-45s %7.3f    %s    %s" % (tokens[0], float(tokens[1]), tokens[2], tokens[3]))
EOF
)

0

có thêm một tùy chọn, sys.stdout.write trả về Không có, giữ cho danh sách trống

cat somefile.log | python -c "import sys; [line for line in sys.stdin if sys.stdout.write (line * 2)]"


0

Nếu bạn không muốn chạm vào stdin và mô phỏng như thể bạn đã vượt qua "python cmdfile.py", bạn có thể thực hiện các thao tác sau từ shell bash:

$ python  <(printf "word=raw_input('Enter word: ')\nimport sys\nfor i in range(5):\n    print(word)")

Như bạn có thể thấy, nó cho phép bạn sử dụng stdin để đọc dữ liệu đầu vào. Bên trong shell tạo tệp tạm thời cho nội dung lệnh đầu vào.


++ vì không "sử dụng hết" stdin với chính tập lệnh (mặc dù -c "$(...)"cũng như vậy và tuân thủ POSIX); để <(...)đặt tên cho cấu trúc: quá trình thay thế ; nó cũng hoạt động trong kshzsh.
mkuity0
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.