Saya menggunakan Python dengan -c
untuk 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.
python
shell
command-line
heredoc
martineau
sumber
sumber
Jawaban:
Anda bisa melakukannya
atau tanpa pipa:
atau
atau @ jawaban SilentGhost / @ jawaban Crast
sumber
python -c "exec(\"import sys\nfor r in range(10): print('rob')\")"
gaya ini dapat digunakan dalam makefiles juga (dan sebenarnya ini cukup sering digunakan).
atau
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 ).
sumber
<<EOF
. Perhatikan, bagaimanapun, bahwa lebih baik untuk mengutip pembatas - misalnya,<<'EOF'
- untuk melindungi isi dokumen di sini dari ekspansi shell di muka .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:
Jika impor menjadi pernyataan adalah masalah, ini akan berhasil, tetapi tidak:
Untuk contoh dasar Anda, Anda dapat menulis ulang sebagai ini:
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
.py
file kecil yang dijalankan oleh makefile Anda?sumber
- Untuk membuat jawaban ini berfungsi dengan Python 3.x juga,
print
disebut sebagai fungsi : dalam 3.x, hanyaprint('foo')
berfungsi, sedangkan 2.x juga menerimaprint 'foo'
.- Untuk perspektif lintas platform yang mencakup Windows , lihat jawaban kxr yang sangat membantu .
Dalam
bash
,ksh
atauzsh
:Gunakan string yang dikutip ANSI C (
$'...'
), yang memungkinkan penggunaan\n
untuk mewakili baris baru yang diperluas ke baris baru yang sebenarnya sebelum string diteruskan kepython
:Catat
\n
antaraimport
danfor
pernyataan untuk menghasilkan jeda baris.Untuk meneruskan nilai variabel-shell ke perintah seperti itu, paling aman menggunakan argumen dan mengaksesnya melalui
sys.argv
di dalam skrip Python: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\n
dalam kasus ini, tetapi juga tersangka seperti\t
,\r
,\b
- yang diperluas dengan$'...'
(lihatman printf
untuk lolos didukung)'
Contoh melarikan diri sebagai\'
.Jika Anda harus tetap mematuhi POSIX :
Gunakan
printf
dengan substitusi perintah :Untuk bekerja dengan aman dengan tipe string ini:
\
Contoh ganda dalam kode sumber asli Anda .\<char>
urutan - seperti\n
dalam kasus ini, tetapi juga tersangka seperti\t
,\r
,\b
- yang diperluas denganprintf
(lihatman printf
untuk escape sequence yang didukung).Lewati string yang dikutip tunggal ke
printf %b
dan 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
$HOME
ke 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.argv
Python; 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.\
pemrosesan shell sendiri dalam string yang dikutip ganda dapat menghalangi; misalnya, untuk mendapatkan Python untuk menghasilkan keluaran literalro\b
, Anda harus mengoperasinyaro\\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 melalui
stdin
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
,ksh
atauzsh
:Gabungkan string yang dikutip ANSI C (
$'...'
) dengan string di sini (<<<...
):-
memberitahupython
secara 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:Jika Anda harus tetap mematuhi POSIX :
Gunakan
printf
seperti di atas, tetapi dengan pipeline untuk meneruskan outputnya melalui stdin:Dengan argumen:
sumber
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 :Pernyataan gabungan tidak dapat dimasukkan pada baris yang sama dengan pernyataan lain melalui titik koma - sehingga melakukan hal ini dengan
-c
flag 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 ,-
: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
<<
:Menempatkan tanda kutip
EOF
mencegah parameter dan ekspansi aritmatika . Ini membuat heredoc lebih kuat.Bash string multiline
Jika Anda menggunakan tanda kutip ganda, Anda akan mendapatkan ekspansi shell:
Untuk menghindari ekspansi shell gunakan tanda kutip tunggal:
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:
Kritik terhadap jawaban yang diterima (dan lainnya)
Ini tidak terlalu mudah dibaca:
Tidak terlalu mudah dibaca, dan juga sulit untuk di-debug jika ada kesalahan:
Mungkin sedikit lebih mudah dibaca, tetapi masih cukup jelek:
Anda akan memiliki waktu yang buruk jika Anda memiliki
"
python:Jangan menyalahgunakan
map
atau mendaftar pemahaman untuk mendapatkan loop:Ini semua menyedihkan dan buruk. Jangan lakukan itu.
sumber
bash
,,ksh
atauzsh
) 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).cukup gunakan return dan ketik di baris berikutnya:
sumber
python $(srcdir)/myscript.py
untuk keadilan yang luar biasa.$ python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"
Bekerja dengan baik. Gunakan "[]" untuk inline for loop Anda.
sumber
Masalahnya bukan dengan
import
pernyataan itu. Masalahnya adalah bahwa pernyataan aliran kontrol tidak bekerja diuraikan dalam perintah python. Gantiimport
pernyataan 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.
sumber
Jika sistem Anda kompatibel dengan Posix.2, ia harus menyediakan
printf
utilitas:sumber
printf %b '...' | python
untuk menambah ketahanan, karena mencegahprintf
dari 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.single/double quotes
dan dibackslash
mana - mana:Jauh lebih baik:
sumber
(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.write
alih-alihprint
( perbedaannya adalah,sys.stdout.write
mengambil argumen sebagai fungsi, dalam tanda kurung - sedangkanprint
tidak ), maka untuk one-liner, Anda bisa lolos dengan membalik urutan perintah danfor
, menghapus tanda titik koma, dan melampirkan perintah dalam tanda kurung, yaitu: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:
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):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 bahwaa
adalahNone
: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 :
Dan memang itu adalah daftar - hanya saja elemen pertamanya menjadi tidak ada begitu dieksekusi:
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":
Perhatikan bahwa "daftar" kedua
b
sekarang memiliki dua elemen, karena untuk loop secara eksplisit berjalan dua kali; Namun, hasil darisys.stdout.write()
kedua kasus itu (tampaknya)None
.sumber
Varian ini paling portabel untuk menempatkan skrip multi-baris pada command-line pada Windows dan * nix, py2 / 3, tanpa pipa:
(Tidak ada contoh lain yang terlihat di sini sejauh ini)
Rapi di Windows adalah:
Rapi saat bash / * nix adalah:
Fungsi ini mengubah skrip multiline menjadi perintah-satu-liner portabel:
Pemakaian:
Masukan tadinya:
sumber
--%
sebelum argumen string-perintah.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.)$foo
dalam kode Python Anda? Jika Anda menghindarinya\$foo
untuk mendapatkan manfaat kerang mirip POSIX, Andacmd.exe
masih akan melihat tambahannya\
. Ini mungkin jarang tetapi perlu diketahui.Script ini menyediakan antarmuka baris perintah seperti Perl:
Pyliner - Script untuk menjalankan kode Python sewenang-wenang pada baris perintah (resep Python)
sumber
Ketika saya perlu melakukan ini, saya menggunakan
Perhatikan triple backslash untuk baris baru dalam pernyataan sys.stdout.write.
sumber
echo -e
, yang tidak standar dan membutuhkanbash
,,ksh
atauzsh
, Anda sebaiknya menggunakan$'...'
string secara langsung, yang juga menyederhanakan pelarian:python -c $'import sys\nsys.stdout.write("Hello World!\\n")'
Saya ingin solusi dengan properti berikut:
Kedua persyaratan tidak disediakan dalam jawaban lain, jadi inilah cara membaca stdin saat melakukan segala sesuatu di baris perintah:
sumber
ada satu opsi lagi, sys.stdout.write mengembalikan Tidak ada, yang membuat daftar kosong
sumber
Jika Anda tidak ingin menyentuh stdin dan mensimulasikan seolah-olah Anda telah melewati "python cmdfile.py", Anda dapat melakukan hal berikut dari bash shell:
Seperti yang Anda lihat, ini memungkinkan Anda untuk menggunakan stdin untuk membaca data input. Secara internal shell membuat file sementara untuk isi perintah input.
sumber
-c "$(...)"
melakukan hal yang sama, dan POSIX-compliant); untuk memberi nama<(...)
konstruk: substitusi proses ; ini juga berfungsi diksh
danzsh
.