Menjalankan pernyataan multi-baris dalam satu-baris perintah?


197

Saya menggunakan Python dengan -cuntuk menjalankan loop satu-liner, yaitu:

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

Ini berfungsi dengan baik. Namun, jika saya mengimpor modul sebelum for for, saya mendapatkan kesalahan sintaks:

$ 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

Adakah yang tahu bagaimana hal ini dapat diperbaiki?

Penting bagi saya untuk memiliki ini sebagai satu-baris sehingga saya bisa memasukkannya ke dalam Makefile.


Jawaban:


182

Anda bisa melakukannya

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

atau tanpa pipa:

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

atau

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

atau @ jawaban SilentGhost / @ jawaban Crast


Opsi terakhir berfungsi sangat baik dengan python3 di Windows
Ian Ellis

1
@RudolfOlah harap Anda tahu itu sekarang tetapi hanya untuk referensi, Anda perlu membungkus pernyataan cetak untuk versi python3 + seperti:python -c "exec(\"import sys\nfor r in range(10): print('rob')\")"
systrigger

@systrigger terima kasih, saya merindukan bahwa saya pikir saya sedang terburu-buru dan tidak menyadari bahwa heh

89

gaya ini dapat digunakan dalam makefiles juga (dan sebenarnya ini cukup sering digunakan).

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

atau

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

dalam kasus terakhir karakter tab utama juga dihapus (dan beberapa pandangan terstruktur dapat dicapai)

alih-alih EOF dapat berdiri kata penanda apa pun yang tidak muncul dalam dokumen di sini di awal baris (lihat juga di sini dokumen di bash manpage atau di sini ).


9
Bagus. Untuk juga memberikan argumen , cukup tempatkan setelah <<EOF. Perhatikan, bagaimanapun, bahwa lebih baik untuk mengutip pembatas - misalnya, <<'EOF'- untuk melindungi isi dokumen di sini dari ekspansi shell di muka .
mklement0

56

Masalahnya sebenarnya bukan dengan pernyataan impor, itu dengan apa pun sebelum loop for. Atau lebih khusus lagi, apa pun yang muncul sebelum blok inline.

Misalnya, semua ini berfungsi:

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

Jika impor menjadi pernyataan adalah masalah, ini akan berhasil, tetapi tidak:

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

Untuk contoh dasar Anda, Anda dapat menulis ulang sebagai ini:

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

Namun, lambdas hanya dapat menjalankan ekspresi, bukan pernyataan atau banyak pernyataan, sehingga Anda mungkin masih tidak dapat melakukan hal yang ingin Anda lakukan. Namun, di antara ekspresi generator, pemahaman daftar, lambdas, sys.stdout.write, "map" bawaan, dan beberapa interpolasi string kreatif, Anda dapat melakukan beberapa liner yang kuat.

Pertanyaannya adalah, seberapa jauh Anda ingin melangkah, dan pada titik apa tidak lebih baik untuk menulis .pyfile kecil yang dijalankan oleh makefile Anda?


31


- Untuk membuat jawaban ini berfungsi dengan Python 3.x juga, printdisebut sebagai fungsi : dalam 3.x, hanya print('foo') berfungsi, sedangkan 2.x juga menerima print 'foo'.
- Untuk perspektif lintas platform yang mencakup Windows , lihat jawaban kxr yang sangat membantu .

Dalam bash, kshatauzsh :

Gunakan string yang dikutip ANSI C ( $'...'), yang memungkinkan penggunaan \nuntuk mewakili baris baru yang diperluas ke baris baru yang sebenarnya sebelum string diteruskan ke python:

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

Catat \nantara importdan forpernyataan untuk menghasilkan jeda baris.

Untuk meneruskan nilai variabel-shell ke perintah seperti itu, paling aman menggunakan argumen dan mengaksesnya melalui sys.argvdi dalam skrip Python:

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

Lihat di bawah untuk pembahasan pro dan kontra menggunakan string perintah yang dikutip ganda (escape sequence-preprocessed) dengan referensi variabel shell yang tertanam .

Untuk bekerja dengan aman dengan $'...'string:

  • \Contoh ganda dalam kode sumber asli Anda .
    • \<char>urutan - seperti \ndalam kasus ini, tetapi juga tersangka seperti \t, \r, \b- yang diperluas dengan $'...'(lihat man printfuntuk lolos didukung)
  • 'Contoh melarikan diri sebagai \'.

Jika Anda harus tetap mematuhi POSIX :

Gunakan printfdengan substitusi perintah :

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

Untuk bekerja dengan aman dengan tipe string ini:

  • \Contoh ganda dalam kode sumber asli Anda .
    • \<char>urutan - seperti \ndalam kasus ini, tetapi juga tersangka seperti \t, \r, \b- yang diperluas dengan printf(lihat man printfuntuk escape sequence yang didukung).
  • Lewati string yang dikutip tunggal ke printf %bdan lepas dari kutipan tunggal yang disematkan sebagai '\'' (sic).

    • Menggunakan tanda kutip tunggal melindungi isi string dari interpretasi oleh shell .

      • Yang mengatakan, untuk skrip Python pendek (seperti dalam kasus ini) Anda dapat menggunakan string yang dikutip ganda untuk memasukkan nilai variabel shell ke skrip Anda - selama Anda mengetahui jebakan terkait (lihat poin berikutnya); misalnya, shell mengembang $HOMEke direktori home pengguna saat ini. dalam perintah berikut:

        • python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
      • Namun, pendekatan yang umumnya lebih disukai adalah untuk memberikan nilai dari shell melalui argumen , dan mengaksesnya melalui sys.argvPython; setara dengan perintah di atas adalah:

        • python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
    • Meskipun menggunakan string yang dikutip ganda lebih mudah - ini memungkinkan Anda untuk menggunakan tanda kutip tunggal yang tertanam tanpa kutip dan melekatkan tanda kutip ganda sebagai \"- itu juga membuat string tunduk pada interpretasi oleh shell , yang mungkin atau mungkin bukan maksudnya; $dan `karakter dalam kode sumber Anda yang tidak dimaksudkan untuk shell dapat menyebabkan kesalahan sintaks atau mengubah string secara tidak terduga.

      • Selain itu, \pemrosesan shell sendiri dalam string yang dikutip ganda dapat menghalangi; misalnya, untuk mendapatkan Python untuk menghasilkan keluaran literal ro\b, Anda harus mengoperasinya ro\\b; dengan '...'string shell dan instance yang digandakan \ , kita mendapatkan:
        python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
        Sebaliknya, ini tidak berfungsi sebagaimana dimaksud dengan "..."string shell:
        python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs'
        Shell menginterpretasikan keduanya "\b" dan "\\b"secara literal \b, membutuhkan jumlah \instance tambahan yang memusingkan untuk mencapai efek yang diinginkan:
        python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"

Untuk meneruskan kode melaluistdin daripada -c:

Catatan: Saya fokus pada solusi single- line di sini; Jawaban xorho menunjukkan bagaimana menggunakan multi-line di sini-dokumen - pastikan untuk mengutip pembatas, namun; mis. <<'EOF', kecuali Anda secara eksplisit ingin shell memperluas string di depan (yang disertai dengan peringatan yang disebutkan di atas).


Dalam bash, kshatauzsh :

Gabungkan string yang dikutip ANSI C ( $'...') dengan string di sini ( <<<...):

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

-memberitahu pythonsecara eksplisit untuk membaca dari stdin (yang tidak secara default). -opsional dalam kasus ini, tetapi jika Anda juga ingin memberikan argumen ke skrip, Anda perlu argumen tersebut untuk mendua argumen dari nama file skrip:

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

Jika Anda harus tetap mematuhi POSIX :

Gunakan printfseperti di atas, tetapi dengan pipeline untuk meneruskan outputnya melalui stdin:

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

Dengan argumen:

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

2
Ini harus menjadi jawaban yang dipilih!
debuti

1
Ini juga berfungsi dan mungkin merupakan jawaban terbaik karena ini mencakup penjelasan lengkap, bravo!

22

Adakah yang tahu bagaimana hal ini dapat diperbaiki?

Masalah Anda dibuat oleh fakta bahwa pernyataan Python, dipisahkan oleh ;, hanya diizinkan menjadi "pernyataan kecil", yang semuanya adalah satu kalimat. Dari file tata bahasa di dokumen 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)

Pernyataan gabungan tidak dapat dimasukkan pada baris yang sama dengan pernyataan lain melalui titik koma - sehingga melakukan hal ini dengan -cflag menjadi sangat merepotkan.

Saat mendemonstrasikan Python saat berada di lingkungan bash shell, saya merasa sangat berguna untuk menyertakan pernyataan majemuk. Satu-satunya cara sederhana untuk melakukan ini dengan andal adalah dengan heredocs (hal shell posix).

Heredocs

Gunakan heredoc (dibuat dengan <<) dan Python pilihan antarmuka baris perintah , -:

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

Menambahkan -after <<(the <<-) memungkinkan Anda untuk menggunakan tab untuk indent (Stackoverflow mengkonversi tab ke spasi, jadi saya telah membuat indentasi 8 spasi untuk menekankan ini). Tab terkemuka akan dilucuti.

Anda dapat melakukannya tanpa tab hanya dengan <<:

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

Menempatkan tanda kutip EOFmencegah parameter dan ekspansi aritmatika . Ini membuat heredoc lebih kuat.

Bash string multiline

Jika Anda menggunakan tanda kutip ganda, Anda akan mendapatkan ekspansi shell:

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

Untuk menghindari ekspansi shell gunakan tanda kutip tunggal:

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

Perhatikan bahwa kita perlu menukar karakter kutipan pada literal dengan Python - kita pada dasarnya tidak dapat menggunakan karakter kutipan yang ditafsirkan oleh BASH. Kita bisa mengganti mereka, seperti yang kita bisa di Python - tetapi ini sudah terlihat cukup membingungkan, itulah sebabnya saya tidak merekomendasikan ini:

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

Kritik terhadap jawaban yang diterima (dan lainnya)

Ini tidak terlalu mudah dibaca:

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

Tidak terlalu mudah dibaca, dan juga sulit untuk di-debug jika ada kesalahan:

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

Mungkin sedikit lebih mudah dibaca, tetapi masih cukup jelek:

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

Anda akan memiliki waktu yang buruk jika Anda memiliki "python:

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

Jangan menyalahgunakan mapatau mendaftar pemahaman untuk mendapatkan loop:

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

Ini semua menyedihkan dan buruk. Jangan lakukan itu.


3
++ untuk info tata bahasa; (non-perluasan) di sini-doc berguna dan solusi yang paling kuat, tetapi jelas bukan satu-liner. Jika solusi single-line adalah suatu keharusan, menggunakan string ANSI C yang dikutip ( bash,, kshatau zsh) adalah solusi yang masuk akal: python -c $'import sys\nfor r in range(10): print(\'rob\')'(Anda hanya perlu khawatir lolos dari tanda kutip tunggal (yang dapat Anda hindari dengan menggunakan tanda kutip ganda) dan backslash).
mklement0

14

cukup gunakan return dan ketik di baris berikutnya:

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

6
Serius, Anda akan keseleo sesuatu jika Anda terus melakukan ini. python $(srcdir)/myscript.pyuntuk keadilan yang luar biasa.
Jason Orendorff

10

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

Bekerja dengan baik. Gunakan "[]" untuk inline for loop Anda.


9

Masalahnya bukan dengan importpernyataan itu. Masalahnya adalah bahwa pernyataan aliran kontrol tidak bekerja diuraikan dalam perintah python. Ganti importpernyataan itu dengan pernyataan lain dan Anda akan melihat masalah yang sama.

Pikirkan tentang hal ini: python tidak mungkin dapat mengatur semuanya. Ini menggunakan lekukan untuk aliran kontrol grup.


7

Jika sistem Anda kompatibel dengan Posix.2, ia harus menyediakan printfutilitas:

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

2
Solusi yang bagus, tetapi saya sarankan menggunakan printf %b '...' | pythonuntuk menambah ketahanan, karena mencegah printfdari menafsirkan urutan seperti %d(format specifier) ​​dalam string input. Selain itu, kecuali jika Anda secara eksplisit ingin menerapkan ekspansi shell ke string perintah Python Anda di muka (yang dapat membingungkan), lebih baik menggunakan '(tanda kutip tunggal) untuk kutipan luar, untuk menghindari ekspansi dan pemrosesan backlash yang diterapkan shell. untuk string dikutip ganda.
mklement0

5

single/double quotesdan di backslashmana - mana:

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

Jauh lebih baik:

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

begitu. banyak. lebih baik.
Marc

4

(dijawab 23 Nov '10 pada 19:48) Saya bukan Pythoner besar - tapi saya menemukan sintaks ini satu kali, lupa dari mana, jadi saya pikir saya akan mendokumentasikannya:

jika Anda menggunakan sys.stdout.writealih-alih print( perbedaannya adalah, sys.stdout.writemengambil argumen sebagai fungsi, dalam tanda kurung - sedangkan printtidak ), maka untuk one-liner, Anda bisa lolos dengan membalik urutan perintah dan for, menghapus tanda titik koma, dan melampirkan perintah dalam tanda kurung, yaitu:

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

Tidak tahu bagaimana sintaks ini akan dipanggil dengan Python :)

Semoga ini membantu,

Bersulang!


(EDIT Sel 9 Apr 20:57:30 2013) Yah, saya pikir saya akhirnya menemukan apa tanda kurung kotak ini dalam satu baris; mereka adalah "daftar pemahaman" (tampaknya); perhatikan ini dengan 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>

Jadi perintah dalam kurung bulat / tanda kurung dilihat sebagai "objek generator"; jika kita "mengulanginya" dengan memanggil next()- maka perintah di dalam tanda kurung akan dieksekusi (perhatikan "abc" di output):

$ 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>

Jika sekarang kita menggunakan tanda kurung siku - perhatikan bahwa kita tidak perlu memanggil next()untuk menjalankan perintah, perintah dijalankan segera setelah penugasan; Namun, pemeriksaan kemudian mengungkapkan bahwa aadalah None:

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

Ini tidak meninggalkan banyak info untuk dicari, untuk kotak kurung - tapi saya menemukan halaman ini yang menurut saya menjelaskan:

Tips Dan Trik Python - Edisi Pertama - Tutorial Python | Kode Mimpi :

Jika Anda ingat, format standar generator jalur tunggal adalah semacam loop satu baris 'untuk' loop di dalam kurung. Ini akan menghasilkan objek iterable 'satu tembakan' yang merupakan objek yang dapat Anda ulangi hanya dalam satu arah dan yang tidak dapat Anda gunakan kembali setelah mencapai akhir.

'Pemahaman daftar' terlihat hampir sama dengan generator satu baris biasa, kecuali bahwa tanda kurung reguler - () - diganti dengan tanda kurung siku - []. Keuntungan utama dari pemahaman alist adalah menghasilkan 'daftar', bukan 'objek satu-shot' yang dapat diulang, sehingga Anda dapat bolak-balik melewatinya, menambahkan elemen, mengurutkan, dll.

Dan memang itu adalah daftar - hanya saja elemen pertamanya menjadi tidak ada begitu dieksekusi:

$ 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

Pemahaman daftar didokumentasikan dalam 5. Struktur Data: 5.1.4. Daftar Pemahaman - Dokumentasi Python v2.7.4 sebagai "Pemahaman daftar menyediakan cara ringkas untuk membuat daftar"; mungkin, di situlah "eksekusi" terbatas dari daftar berperan dalam satu-liners.

Yah, semoga aku tidak terlalu melenceng di sini ...

EDIT2: dan di sini adalah baris perintah satu-liner dengan dua loop-non-bersarang; keduanya tertutup dalam tanda kurung siku "daftar pemahaman":

$ 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]

Perhatikan bahwa "daftar" kedua bsekarang memiliki dua elemen, karena untuk loop secara eksplisit berjalan dua kali; Namun, hasil dari sys.stdout.write()kedua kasus itu (tampaknya) None.


4

Varian ini paling portabel untuk menempatkan skrip multi-baris pada command-line pada Windows dan * nix, py2 / 3, tanpa pipa:

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

(Tidak ada contoh lain yang terlihat di sini sejauh ini)

Rapi di Windows adalah:

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

Rapi saat bash / * nix adalah:

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

Fungsi ini mengubah skrip multiline menjadi perintah-satu-liner portabel:

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

Pemakaian:

>>> 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\"\"\"')"

Masukan tadinya:

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

++ untuk sudut lintas platform dan konverter. Perintah pertama Anda sama baiknya dengan portabilitas (mengabaikan PowerShell), tetapi pada akhirnya tidak ada sintaksis lintas-platform tunggal yang sepenuhnya kuat , karena kebutuhan untuk menggunakan tanda kutip ganda kemudian menanggung risiko ekspansi shell yang tidak diinginkan, dengan Windows membutuhkan pelarian karakter yang berbeda dari kerang mirip POSIX. Di PowerShell v3 atau lebih tinggi, Anda dapat membuat baris perintah Anda berfungsi dengan memasukkan opsi "stop-parsing" --%sebelum argumen string-perintah.
mklement0

@ mklement0 " ekspansi shell yang tidak diinginkan ": well, penyisipan ekspansi shell menjadi sesuatu seperti print "path is %%PATH%%"resp. print "path is $PATH"biasanya merupakan opsi yang diinginkan seseorang dalam skrip atau baris perintah - kecuali ada yang lolos dari platform. Sama dengan bahasa lain. (Sintaksis Python itu sendiri tidak secara teratur menyarankan penggunaan% dan $ dalam cara yang bersaing.)
kxr

Jika Anda memasukkan referensi variabel-shell secara langsung ke dalam kode sumber Python, itu menurut definisi tidak akan portabel. Maksud saya adalah bahwa bahkan jika Anda bukan dibangun referensi platform-spesifik di terpisah variabel yang Anda lulus sebagai argumen untuk , "shell bebas" tunggal perintah Python, yang mungkin tidak selalu bekerja, karena Anda tidak dapat melindungi string dikutip ganda portable : misal, bagaimana jika Anda membutuhkan literal $foo dalam kode Python Anda? Jika Anda menghindarinya \$foountuk mendapatkan manfaat kerang mirip POSIX, Anda cmd.exemasih akan melihat tambahannya \ . Ini mungkin jarang tetapi perlu diketahui.
mklement0

Mencoba melakukan ini di Windows PowerShell, tetapi masalahnya adalah python -c exec ("" "..." "") tidak menghasilkan output apa pun, tidak masalah apakah kode di ... dapat dieksekusi atau tidak; Saya bisa menaruh omong kosong di sana, dan hasilnya akan sama. Saya merasa seperti cangkang sedang "memakan" aliran stdout dan stderr - bagaimana saya bisa membuatnya meludahkan mereka?
Yury

2

Saya pikir mereka menginginkan sesuatu untuk memperbaikinya, bukan menggunakan alat lain. Pokoknya petunjuk yang bagus
enrico.bacis

Saya setuju dengan @ enrico.bacis, tetapi saya masih senang Anda menambahkan jawaban ini. Itu menjawab pertanyaan yang saya miliki ketika saya mencari Google di halaman ini.
tbc0

1

Ketika saya perlu melakukan ini, saya menggunakan

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

Perhatikan triple backslash untuk baris baru dalam pernyataan sys.stdout.write.


Ini berfungsi, tetapi karena Anda menggunakan echo -e, yang tidak standar dan membutuhkan bash,, kshatau zsh, Anda sebaiknya menggunakan $'...'string secara langsung, yang juga menyederhanakan pelarian:python -c $'import sys\nsys.stdout.write("Hello World!\\n")'
mklement0

Jawaban ini berfungsi, jawaban lain tidak berfungsi untuk Python3

1

Saya ingin solusi dengan properti berikut:

  1. Dapat dibaca
  2. Baca stdin untuk memproses output dari alat lain

Kedua persyaratan tidak disediakan dalam jawaban lain, jadi inilah cara membaca stdin saat melakukan segala sesuatu di baris perintah:

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

ada satu opsi lagi, sys.stdout.write mengembalikan Tidak ada, yang membuat daftar kosong

cat somefile.log | python -c "import sys; [baris untuk baris di sys.stdin jika sys.stdout.write (baris * 2)]"


0

Jika Anda tidak ingin menyentuh stdin dan mensimulasikan seolah-olah Anda telah melewati "python cmdfile.py", Anda dapat melakukan hal berikut dari bash shell:

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

Seperti yang Anda lihat, ini memungkinkan Anda untuk menggunakan stdin untuk membaca data input. Secara internal shell membuat file sementara untuk isi perintah input.


++ untuk tidak "menggunakan" stdin dengan skrip itu sendiri (meskipun -c "$(...)"melakukan hal yang sama, dan POSIX-compliant); untuk memberi nama <(...)konstruk: substitusi proses ; ini juga berfungsi di kshdan zsh.
mklement0
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.