Bagaimana cara mengimplementasikan idiom bash umum di Python? [Tutup]

242

Saat ini saya melakukan manipulasi file teks saya melalui sekelompok AWK, sed, Bash dan sedikit Perl.

Saya telah melihat menyebutkan beberapa tempat bahwa python baik untuk hal semacam ini. Bagaimana saya bisa menggunakan Python untuk mengganti skrip shell, AWK, sed dan teman-teman?

Chris Jefferson
sumber
3
pythonpy adalah pesaing yang baik untuk awk dan sed menggunakan sintaksis python: github.com/Russell91/pythonpy
RussellStewart
4
Anda dapat menggunakan shellpy yang dirancang dengan ide untuk menggantikan bash / sh dengan python github.com/lamerman/shellpy
Alexander Ponomarev
Ini adalah pertanyaan saya, saya tidak mengerti mengapa itu berdasarkan pendapat. Jawaban teratas mencantumkan setiap hal utama yang dilakukan oleh shell, dan memberi tahu Anda cara melakukannya dengan python. Itu menurut saya menjawab pertanyaan dengan cara yang bukan pendapat.
Chris Jefferson
Pertanyaan ini, dan ini adalah penutupan, sedang dibahas dalam meta di sini
Erik A

Jawaban:

144

Setiap shell memiliki beberapa set fitur.

  • Perintah Essential Linux / Unix. Semua ini tersedia melalui perpustakaan subproses . Ini tidak selalu merupakan pilihan pertama terbaik untuk melakukan semua perintah eksternal. Lihat juga di shutil untuk beberapa perintah yang merupakan perintah Linux yang terpisah, tetapi Anda mungkin bisa mengimplementasikannya langsung di skrip Python Anda. Sejumlah besar perintah Linux ada di perpustakaan os ; Anda dapat melakukan ini lebih sederhana dengan Python.

    Dan - bonus! -- lebih cepat. Setiap perintah Linux yang terpisah di shell (dengan beberapa pengecualian) bercabang menjadi subproses. Dengan menggunakan Python shutildan osmodul, Anda tidak perlu melakukan subproses.

  • Fitur lingkungan shell. Ini termasuk hal-hal yang menetapkan lingkungan perintah (direktori saat ini dan variabel lingkungan dan apa-tidak). Anda dapat dengan mudah mengelola ini dari Python secara langsung.

  • Fitur pemrograman shell. Ini semua proses kode status memeriksa, berbagai perintah logika (jika, sementara, untuk, dll) perintah uji dan semua kerabat itu. Hal-hal definisi fungsi. Ini semua, jauh lebih mudah dengan Python. Ini adalah salah satu kemenangan besar dalam menyingkirkan bash dan melakukannya dengan Python.

  • Fitur interaksi. Ini termasuk sejarah perintah dan apa yang tidak. Anda tidak memerlukan ini untuk menulis skrip shell. Ini hanya untuk interaksi manusia, dan bukan untuk penulisan naskah.

  • Fitur manajemen file shell. Ini termasuk pengalihan dan jalur pipa. Ini lebih sulit. Banyak dari ini dapat dilakukan dengan subproses. Tetapi beberapa hal yang mudah di shell tidak menyenangkan di Python. Khususnya hal-hal seperti (a | b; c ) | something >result. Ini menjalankan dua proses secara paralel (dengan output asebagai input ke b), diikuti oleh proses ketiga. Output dari urutan itu dijalankan secara paralel dengan somethingdan output dikumpulkan ke file bernama result. Itu kompleks untuk diekspresikan dalam bahasa lain.

Program spesifik (awk, sed, grep, dll.) Seringkali dapat ditulis ulang sebagai modul Python. Jangan berlebihan. Ganti apa yang Anda butuhkan dan kembangkan modul "grep" Anda. Jangan mulai menulis modul Python yang menggantikan "grep".

Yang terbaik adalah Anda bisa melakukan ini dalam langkah-langkah.

  1. Ganti AWK dan PERL dengan Python. Tinggalkan yang lainnya sendirian.
  2. Lihatlah mengganti GREP dengan Python. Ini mungkin sedikit lebih rumit, tetapi versi GREP Anda dapat disesuaikan dengan kebutuhan pemrosesan Anda.
  3. Lihatlah mengganti FIND dengan loop Python yang digunakan os.walk. Ini adalah kemenangan besar karena Anda tidak menelurkan banyak proses.
  4. Lihatlah mengganti logika shell umum (loop, keputusan, dll.) Dengan skrip Python.
S.Lott
sumber
6
menulis: "Fitur interaksi. Ini termasuk riwayat perintah dan apa-tidak. Anda tidak memerlukan ini." Saya khawatir tidak ada yang tahu apa yang benar-benar dibutuhkan atau tidak. Mungkin dia melakukannya. Selain itu, fasilitas ini sangat masuk akal dalam shell interaktif, dengan mengambil contoh perbedaan antara Idle dan IPython.
heltonbiker
47
Saya sungguh berharap orang-orang akan meninggalkan skrip shell sama sekali. Saya mengerti bahwa peretasan secara praktis adalah agama di dunia * nix, tetapi saya benar-benar lelah mencoba menafsirkan semua solusi peretasan yang ditanamkan dalam OS. Kebaruan mikrotool (awk, sed, top, base, dll) hilang ketika semua orang memutuskan untuk meluncurkan versi mereka sendiri. Saya merasa ngeri ketika saya membayangkan jumlah jam kerja yang terbuang sia-sia pada alat-alat kecil yang jelek yang dapat dengan mudah digantikan oleh beberapa modul Python yang dirancang dengan baik. :: sigh ::
Evan Plaice
40
Saya tidak setuju @EvanPlaice karena versi python dari beberapa findskrip yang saya miliki jelek dan panjang dan tidak dapat dibandingkan. Banyak hal yang harus berupa skrip shell, banyak lainnya tidak . Tidak semuanya perlu hanya satu dari Python atau BASH (atau apa pun).
mikebabcock
8
@mikebabcock Idealnya akan ada perpustakaan lengkap yang mengimplementasikan semua alat-mikro yang disediakan oleh tumpukan * nix dasar. Fungsi seperti find () dan last () akan dimasukkan dan alih-alih pipa, kombinasi currying dan lazy-loading akan menangani pengeleman semuanya. Bukankah lebih baik memiliki lingkungan scripting POSIX yang bekerja dengan cara standar di semua distro? Tidak ada yang seperti itu ada, namun ...
Evan Plaice
2
Poin tentang pipeline shell (seperti (a | b; c ) | something >result) agak dimitigasi olehnya karena mudah untuk melewati pipeline shell ke subprocessmetode menggunakanshell=True
iruvar
103

Ya tentu saja :)

Lihatlah perpustakaan-perpustakaan ini yang membantu Anda Jangan pernah menulis skrip shell lagi (moto Plumbum).

Juga, jika Anda ingin mengganti awk, sed dan grep dengan sesuatu yang berbasis Python maka saya sarankan pyp -

"The Pyed Piper", atau pyp, adalah alat manipulasi teks baris perintah linux mirip dengan awk atau sed, tetapi yang menggunakan string python standar dan metode daftar serta fungsi kustom berkembang untuk menghasilkan hasil yang cepat dalam lingkungan produksi yang intens.

Piotr Dobrogost
sumber
Lihat juga Utusan, yang merupakan alternatif untuk sh github.com/kennethreitz/envoy
AllanLRH
57

Saya baru saja menemukan cara menggabungkan bagian terbaik dari bash dan ipython. Sampai sekarang ini terasa lebih nyaman bagi saya daripada menggunakan subproses dan sebagainya. Anda dapat dengan mudah menyalin sebagian besar skrip bash yang ada dan misalnya menambahkan penanganan kesalahan dengan cara python :) Dan inilah hasil saya:

#!/usr/bin/env ipython3

# *** How to have the most comfort scripting experience of your life ***
# ######################################################################
#
# … by using ipython for scripting combined with subcommands from bash!
#
# 1. echo "#!/usr/bin/env ipython3" > scriptname.ipy    # creates new ipy-file
#
# 2. chmod +x scriptname.ipy                            # make in executable
#
# 3. starting with line 2, write normal python or do some of
#    the ! magic of ipython, so that you can use unix commands
#    within python and even assign their output to a variable via
#    var = !cmd1 | cmd2 | cmd3                          # enjoy ;)
#
# 4. run via ./scriptname.ipy - if it fails with recognizing % and !
#    but parses raw python fine, please check again for the .ipy suffix

# ugly example, please go and find more in the wild
files = !ls *.* | grep "y"
for file in files:
  !echo $file | grep "p"
# sorry for this nonsense example ;)

Lihat dokumen IPython pada perintah shell sistem dan menggunakannya sebagai shell sistem .

TheK
sumber
11
Terpilih karena beberapa alasan aneh, tidak ada orang lain yang menyebutkan! -Perintah dalam IPython, yang benar-benar penting; terutama karena Anda juga dapat menetapkan output mereka ke variabel (daftar baris) seperti difilelines = ! cat myfile
kampu
Dan Anda bisa menggunakan variabel python seperti $varpada perintah shell? Wow. Ini harus menjadi jawaban yang diterima.
Chiel ten Brinke
Dan Anda juga dapat menggunakannya dari dalam notebook jupyter
Yuval Atzmon
44

Pada tahun 2015 dan rilis Python 3.4, sekarang ada shell interaktif-pengguna yang cukup lengkap tersedia di: http://xon.sh/ atau https://github.com/scopatz/xonsh

The video demonstrasi tidak menunjukkan pipa yang digunakan, tetapi mereka ADALAH didukung saat dalam modus shell default.

Xonsh ('Keong') berusaha sangat keras untuk menandingi bash, jadi hal-hal yang sudah Anda dapatkan, misalnya

env | uniq | sort -r | grep PATH

atau

my-web-server 2>&1 | my-log-sorter

masih akan bekerja dengan baik.

Tutorialnya cukup panjang dan tampaknya mencakup sejumlah besar fungsi yang biasanya diharapkan seseorang pada prompt ash atau bash:

  • Kompilasi, Evaluasi, & Eksekusi!
  • Command History dan Tab Completion
  • Bantuan & Superhelp dengan ?&??
  • Alias ​​& Konfirmasi yang Disesuaikan
  • Menjalankan Perintah dan / atau *.xshSkrip yang juga dapat diimpor
  • Variabel Lingkungan termasuk Pencarian dengan ${}
  • Input / Output Redirection dan Combining
  • Latar Belakang Pekerjaan & Kontrol Pekerjaan
  • Subproses Nesting, Pipa, dan Coprocesses
  • Subprocess-mode ketika ada perintah, Python-mode sebaliknya
  • Subproses yang diambil dengan $(), Subproses yang tidak dibaptis dengan $[], Evaluasi Python dengan@()
  • Nama file Globbing dengan *atau Ekspresi Reguler Nama file Globbing dengan Backticks
Kamilion
sumber
Tetapi mengapa sepertinya semua jawaban ini hanya menciptakan kembali roda untuk orang-orang yang tidak tahu bash ? Saya sudah cukup nyaman dengan bash dan setiap jawaban ini sepertinya akan lebih bermanfaat untuk sedikit manfaat. Semua jawaban ini ditujukan untuk orang-orang python yang takut (atau tidak mau menghabiskan waktu belajar) bash, apakah saya benar?
Buttle Butkus
Tampaknya memiliki beberapa kekurangan seperti persyaratan untuk menggunakan .xshekstensi untuk file dengan kode xonsh : github.com/xonsh/xonsh/issues/2478 . Kalau tidak, Anda harus menggunakannya evalxuntuk memanggilnya langsung dari .pyfile.
Andry
31
  • Jika Anda ingin menggunakan Python sebagai shell, mengapa tidak melihat IPython ? Baik juga untuk belajar bahasa secara interaktif.
  • Jika Anda melakukan banyak manipulasi teks, dan jika Anda menggunakan Vim sebagai editor teks, Anda juga dapat langsung menulis plugin untuk Vim dengan python. cukup ketik ": help python" di Vim dan ikuti instruksi atau lihat presentasi ini . Sangat mudah dan kuat untuk menulis fungsi yang akan Anda gunakan langsung di editor Anda!
Mapad
sumber
8
ada profil ipython yang disebut 'sh' yang membuat penerjemah sangat mirip shell.
Autoplectic
3
Profil ipython 'sh' telah dihapus selama beberapa waktu sekarang.
gdw2
>>> hasil =! dmesg | grep -i 'usb' #the! Operator melakukan semuanya
Permafacture
16

Pada awalnya ada sh, sed, dan awk (dan temukan, dan grep, dan ...). Itu bagus. Tetapi awk bisa menjadi binatang kecil yang aneh dan sulit diingat jika Anda tidak sering menggunakannya. Kemudian unta besar menciptakan Perl. Perl adalah impian administrator sistem. Itu seperti skrip shell pada steroid. Pemrosesan teks, termasuk ekspresi reguler hanya bagian dari bahasa. Kemudian menjadi jelek ... Orang-orang mencoba membuat aplikasi besar dengan Perl. Sekarang, jangan salah paham, Perl bisa menjadi aplikasi, tetapi bisa (bisa!) Terlihat berantakan jika Anda tidak benar-benar berhati-hati. Lalu ada semua bisnis data flat ini. Sudah cukup untuk menggerakkan kacang programmer.

Masukkan Python, Ruby, dkk. Ini adalah bahasa tujuan umum yang sangat bagus. Mereka mendukung pemrosesan teks, dan melakukannya dengan baik (meskipun mungkin tidak terjalin erat dalam inti dasar bahasa). Tetapi mereka juga meningkatkan skala dengan baik, dan masih memiliki kode yang terlihat bagus di akhir hari. Mereka juga telah mengembangkan komunitas yang cukup besar dengan banyak perpustakaan untuk hampir semua hal.

Sekarang, banyak dari ketidak-adilan terhadap Perl adalah masalah pendapat, dan tentu saja beberapa orang dapat menulis Perl sangat bersih, tetapi dengan ini banyak orang mengeluh tentang hal itu karena terlalu mudah untuk membuat kode yang dikaburkan, Anda tahu ada beberapa butir kebenaran di sana. Pertanyaannya adalah, apakah Anda akan menggunakan bahasa ini untuk lebih dari sekadar penggantian skrip bash. Jika tidak, pelajari lebih banyak Perl .. itu benar-benar fantastis untuk itu. Di lain pihak, jika Anda menginginkan bahasa yang akan berkembang seiring Anda ingin melakukan lebih banyak, boleh saya sarankan Python atau Ruby.

Either way, semoga berhasil!

MattG
sumber
9

Saya menyarankan buku online yang luar biasa Dive Into Python . Begitulah cara saya mempelajari bahasa aslinya.

Selain mengajari Anda struktur dasar bahasa, dan banyak sekali struktur data yang bermanfaat, ia memiliki bab yang baik tentang penanganan file dan bab-bab selanjutnya tentang ekspresi reguler dan banyak lagi.

Dan Lenski
sumber
1
... masalah utama jawaban hanya tautan.
Jean-François Fabre
7

Menambah jawaban sebelumnya: periksa modul pexpect untuk berurusan dengan perintah interaktif (adduser, passwd dll.)

Federico A. Ramponi
sumber
7

Salah satu alasan saya suka Python adalah karena standarnya jauh lebih baik daripada alat POSIX. Saya harus memeriksa dua kali dan tiga kali lipat bahwa setiap bit kompatibel dengan sistem operasi lain. Program yang ditulis pada sistem Linux mungkin tidak berfungsi sama pada sistem BSD OSX. Dengan Python, saya hanya perlu memeriksa bahwa sistem target memiliki versi Python yang cukup modern.

Bahkan lebih baik, program yang ditulis dengan Python standar bahkan akan berjalan di Windows!

Hal Canary
sumber
1
"sebuah program yang ditulis dengan standar Python bahkan akan berjalan di Windows": tidak bercanda?
Jean-François Fabre
6

Di sini saya akan memberikan pendapat saya berdasarkan pengalaman:

Untuk shell:

  • shell dapat dengan mudah menelurkan kode read-only. Tulis dan ketika Anda kembali ke sana, Anda tidak akan pernah tahu apa yang Anda lakukan lagi. Sangat mudah untuk mencapai ini.
  • shell dapat melakukan BANYAK pemrosesan teks, pemisahan, dll dalam satu baris dengan pipa.
  • itu adalah bahasa lem terbaik ketika datang untuk mengintegrasikan panggilan program dalam berbagai bahasa pemrograman.

Untuk python:

  • jika Anda ingin mudah dibawa ke windows, gunakan python.
  • python bisa lebih baik ketika Anda harus memanipulasi lebih dari sekedar teks, seperti kumpulan angka. Untuk ini, saya sarankan python.

Saya biasanya memilih bash untuk sebagian besar hal, tetapi ketika saya memiliki sesuatu yang harus melewati batas windows, saya hanya menggunakan python.

Germán Diago
sumber
4

pythonpy adalah alat yang menyediakan akses mudah ke banyak fitur dari awk dan sed, tetapi menggunakan sintaksis python:

$ echo me2 | py -x 're.sub("me", "you", x)'
you2
RussellStewart
sumber
3

Saya telah membangun skrip shell semi-panjang (300-500 baris) dan kode Python yang melakukan fungsi serupa. Ketika banyak perintah eksternal dieksekusi, saya menemukan shell lebih mudah digunakan. Perl juga merupakan pilihan yang baik ketika ada banyak manipulasi teks.

Mike Davis
sumber
3

Saat meneliti topik ini, saya menemukan kode pembuktian konsep ini (melalui komentar di http://jlebar.com/2010/2/1/Replacing_Bash.html ) yang memungkinkan Anda "menulis pipeline mirip shell di Python menggunakan sintaks singkat, dan meningkatkan alat sistem yang ada di mana mereka masuk akal ":

for line in sh("cat /tmp/junk2") | cut(d=',',f=1) | 'sort' | uniq:
    sys.stdout.write(line)
Nickolay
sumber
2

Taruhan terbaik Anda adalah alat yang secara khusus diarahkan untuk masalah Anda. Jika sedang memproses file teks, maka Sed, Awk, dan Perl adalah pesaing teratas. Python adalah bahasa dinamis tujuan umum . Seperti halnya bahasa tujuan umum, ada dukungan untuk manipulasi file, tetapi bukan itu tujuan intinya. Saya akan mempertimbangkan Python atau Ruby jika saya memiliki persyaratan untuk bahasa yang dinamis pada khususnya.

Singkatnya, pelajari Sed dan Awk dengan sangat baik, ditambah semua barang lain yang datang dengan citarasa * nix Anda (Semua bawaan Bash, grep, tr, dan sebagainya). Jika Anda memproses file teks yang Anda minati, Anda sudah menggunakan hal-hal yang benar.

Eric Smith
sumber
2

Anda bisa menggunakan python alih-alih bash dengan pustaka ShellPy .

Berikut adalah contoh yang mengunduh avatar pengguna Python dari Github:

import json
import os
import tempfile

# get the api answer with curl
answer = `curl https://api.github.com/users/python
# syntactic sugar for checking returncode of executed process for zero
if answer:
    answer_json = json.loads(answer.stdout)
    avatar_url = answer_json['avatar_url']

    destination = os.path.join(tempfile.gettempdir(), 'python.png')

    # execute curl once again, this time to get the image
    result = `curl {avatar_url} > {destination}
    if result:
        # if there were no problems show the file
        p`ls -l {destination}
    else:
        print('Failed to download avatar')

    print('Avatar downloaded')
else:
    print('Failed to access github api')

Seperti yang Anda lihat, semua ekspresi di dalam simbol aksen kubur (`) dieksekusi di shell. Dan dalam kode Python, Anda dapat menangkap hasil dari eksekusi ini dan melakukan tindakan di atasnya. Sebagai contoh:

log = `git log --pretty=oneline --grep='Create'

Baris ini pertama-tama akan mengeksekusi git log --pretty=oneline --grep='Create'di shell dan kemudian menetapkan hasilnya ke variabel log. Hasilnya memiliki sifat-sifat berikut:

stdout seluruh teks dari stdout dari proses yang dieksekusi

stderr seluruh teks dari stderr dari proses yang dieksekusi

returncode returncode dari eksekusi

Ini adalah gambaran umum dari perpustakaan, deskripsi yang lebih rinci dengan contoh-contoh dapat ditemukan di sini .

Alexander Ponomarev
sumber
1

Jika manipulasi file teks Anda biasanya satu kali, mungkin dilakukan pada prompt shell, Anda tidak akan mendapatkan sesuatu yang lebih baik dari python.

Di sisi lain, jika Anda biasanya harus melakukan tugas yang sama (atau serupa) berulang kali, dan Anda harus menulis skrip Anda untuk melakukan itu, maka python hebat - dan Anda dapat dengan mudah membuat perpustakaan Anda sendiri (Anda dapat melakukan itu dengan skrip shell juga, tetapi lebih rumit).

Contoh yang sangat sederhana untuk mendapatkan perasaan.

import popen2
stdout_text, stdin_text=popen2.popen2("your-shell-command-here")
for line in stdout_text:
  if line.startswith("#"):
    pass
  else
    jobID=int(line.split(",")[0].split()[1].lstrip("<").rstrip(">"))
    # do something with jobID

Periksa juga sys dan modul getopt, mereka adalah yang pertama yang Anda perlukan.

Davide
sumber
1

Saya telah menerbitkan paket tentang PyPI: ez .
Gunakan pip install ezuntuk menginstalnya.

Ini telah mengemas perintah-perintah umum dalam shell dan lib saya menggunakan sintaksis yang sama seperti shell. misalnya, cp (sumber, tujuan) dapat menangani file dan folder! (pembungkus shutil.copy shutil.copytree dan memutuskan kapan harus menggunakan yang mana). Lebih bagus lagi, ini dapat mendukung vektorisasi seperti R!

Contoh lain: tanpa os.walk, gunakan fls (path, regex) untuk secara rekursif menemukan file dan memfilter dengan ekspresi reguler dan mengembalikan daftar file dengan atau tanpa fullpath

Contoh terakhir: Anda dapat menggabungkannya untuk menulis skrip yang sangat sederhana:
files = fls('.','py$'); cp(files, myDir)

Pasti memeriksanya! Saya harus menghabiskan ratusan jam untuk menulis / memperbaikinya!

Jerry T
sumber
1
Terlihat menarik, tetapi saya tidak dapat menerobos dokumen yang belum diformat di pypi.python.org/pypi/ez , maaf ...
Greg Dubicki