Làm thế nào để thực hiện các thành ngữ bash phổ biến trong Python? [đóng cửa]


242

Tôi hiện đang thực hiện thao tác xử lý textfile của mình thông qua một loạt AWK, sed, Bash và một chút Perl.

Tôi đã thấy đề cập đến một vài nơi rằng trăn là tốt cho loại điều này. Làm cách nào tôi có thể sử dụng Python để thay thế kịch bản shell, AWK, sed và bạn bè?


3
pythonpy là một đối thủ cạnh tranh tốt cho awk và sed sử dụng cú pháp python: github.com/Russell91/pythonpy
RussellStewart

4
bạn có thể sử dụng shellpy được thiết kế với ý tưởng để thay thế bash / sh bằng python github.com/lamerman/shellpy
Alexander Ponomarev

Đây là câu hỏi của tôi, tôi không hiểu tại sao nó dựa trên ý kiến. Câu trả lời trên cùng liệt kê từng điều chính mà shell thực hiện và cho bạn biết cách thực hiện chúng trong python. Điều đó theo ý kiến ​​của tôi trả lời câu hỏi theo cách không có ý kiến.
Chris Jefferson

Câu hỏi này và nó đã kết thúc, đang được thảo luận trên meta tại đây
Erik A

Câu trả lời:


144

Bất kỳ shell có một số bộ tính năng.

  • Các lệnh Linux / Unix cần thiết. Tất cả những thứ này đều có sẵn thông qua thư viện quy trình con . Đây không phải luôn là lựa chọn đầu tiên tốt nhất để thực hiện tất cả các lệnh bên ngoài. Cũng xem xét tắt một số lệnh là các lệnh Linux riêng biệt, nhưng bạn có thể có thể thực hiện trực tiếp trong các tập lệnh Python của mình. Một loạt các lệnh Linux khổng lồ khác nằm trong thư viện os ; bạn có thể làm những điều này đơn giản hơn trong Python.

    Và - tiền thưởng! -- nhanh hơn nữa. Mỗi lệnh Linux riêng biệt trong trình bao (với một vài ngoại lệ) tạo ra một quy trình con. Bằng cách sử dụng Python shutiloscác mô-đun, bạn không rẽ nhánh một quy trình con.

  • Các tính năng môi trường vỏ. Điều này bao gồm những thứ thiết lập môi trường của lệnh (biến thư mục và biến môi trường hiện tại và những gì không). Bạn có thể dễ dàng quản lý điều này từ Python trực tiếp.

  • Các tính năng lập trình vỏ. Đây là tất cả các kiểm tra mã trạng thái quá trình, các lệnh logic khác nhau (nếu, trong khi, cho, v.v.) lệnh kiểm tra và tất cả các họ hàng của nó. Các công cụ định nghĩa chức năng. Đây là tất cả, dễ dàng hơn nhiều trong Python. Đây là một trong những chiến thắng to lớn trong việc loại bỏ bash và thực hiện nó trong Python.

  • Tính năng tương tác. Điều này bao gồm lịch sử lệnh và những gì không. Bạn không cần điều này để viết kịch bản shell. Điều này chỉ dành cho tương tác của con người, và không dành cho viết kịch bản.

  • Các tính năng quản lý tập tin shell. Điều này bao gồm chuyển hướng và đường ống. Điều này là khó khăn hơn. Phần lớn điều này có thể được thực hiện với quy trình con. Nhưng một số thứ dễ dàng trong shell là khó chịu trong Python. Cụ thể như thế nào (a | b; c ) | something >result. Điều này chạy hai quá trình song song (với đầu ra alà đầu vào b), tiếp theo là quá trình thứ ba. Đầu ra từ chuỗi đó được chạy song song somethingvà đầu ra được thu thập vào một tệp có tên result. Điều đó thật phức tạp để diễn đạt bằng bất kỳ ngôn ngữ nào khác.

Các chương trình cụ thể (awk, sed, grep, v.v.) thường có thể được viết lại dưới dạng các mô-đun Python. Đừng quá nhiệt tình. Thay thế những gì bạn cần và phát triển mô-đun "grep" của bạn. Đừng bắt đầu viết một mô-đun Python thay thế "grep".

Điều tốt nhất là bạn có thể làm điều này trong các bước.

  1. Thay thế AWK và PERL bằng Python. Để mọi thứ khác một mình.
  2. Nhìn vào việc thay thế GREP bằng Python. Điều này có thể phức tạp hơn một chút, nhưng phiên bản GREP của bạn có thể được điều chỉnh theo nhu cầu xử lý của bạn.
  3. Nhìn vào việc thay thế TÌM bằng các vòng lặp Python sử dụng os.walk. Đây là một chiến thắng lớn vì bạn không sinh ra nhiều quá trình.
  4. Nhìn vào việc thay thế logic shell thông thường (vòng lặp, quyết định, v.v.) bằng các tập lệnh Python.

6
đã viết: "Các tính năng tương tác. Điều này bao gồm lịch sử lệnh và những gì không. Bạn không cần điều này." Tôi sợ không ai có thể nói một người thực sự cần gì hay không. Có lẽ anh ấy làm. Bên cạnh đó, các cơ sở này có rất nhiều ý nghĩa trong một vỏ tương tác, lấy ví dụ về sự khác biệt giữa Idle và IPython.
heltonbiker

47
Tôi chân thành mong muốn mọi người sẽ bỏ hoàn toàn kịch bản shell. Tôi hiểu rằng hack thực tế là một tôn giáo trong thế giới * nix nhưng tôi thực sự mệt mỏi khi cố gắng diễn giải tất cả các cách giải quyết hack được cấy trong HĐH. Sự mới lạ của microtools (awk, sed, top, base, v.v.) đã biến mất vào ngày mọi người quyết định tung ra phiên bản của riêng họ. Tôi co rúm người lại khi tưởng tượng lượng thời gian của con người bị lãng phí cho các công cụ nhỏ bé xảo quyệt có thể dễ dàng thay thế bằng một vài mô-đun Python được thiết kế tốt. :: thở dài ::
Evan Plaice

40
Tôi không đồng ý @EvanPlaice vì phiên bản python của một số findscript tôi có là xấu và dài và không thể so sánh được. Nhiều thứ nên là shell script, nhiều thứ khác thì không . Không phải mọi thứ chỉ cần là một trong Python hoặc BASH (hoặc bất cứ thứ gì khác).
mikebabcock

8
@mikebabcock Lý tưởng nhất là sẽ có một thư viện hoàn chỉnh thực hiện tất cả các công cụ vi mô được cung cấp bởi ngăn xếp * nix cơ bản. Các hàm như find () và last () sẽ được bao gồm và thay vì các đường ống, sự kết hợp giữa cà ri và tải lười biếng sẽ xử lý việc dán tất cả lại với nhau. Sẽ không tốt nếu có một môi trường kịch bản POSIX hoạt động theo cách tiêu chuẩn trên tất cả các bản phát hành? Không có gì giống như vậy tồn tại, nhưng ...
Evan Plaice

2
Điểm về đường ống vỏ (chẳng hạn như (a | b; c ) | something >result) phần nào được giảm nhẹ bởi nó rất dễ dàng để vượt qua đường ống vỏ cho subprocesscác phương pháp sử dụngshell=True
iruvar

103

Phải, tất nhiên :)

Hãy xem những thư viện này giúp bạn Không bao giờ viết kịch bản shell nữa (phương châm của Plumbum).

Ngoài ra, nếu bạn muốn thay thế awk, sed và grep bằng thứ gì đó dựa trên Python thì tôi khuyên bạn nên dùng pyp -

"The Pyed Piper", hay pyp, là một công cụ xử lý văn bản dòng lệnh linux tương tự như awk hoặc sed, nhưng sử dụng các chuỗi python tiêu chuẩn và các phương thức liệt kê cũng như các chức năng tùy chỉnh được phát triển để tạo ra kết quả nhanh trong môi trường sản xuất cường độ cao.


Ngoài ra, hãy xem Envoy, một thay thế cho sh github.com/kennethreitz/envoy
AllanLRH

57

Tôi mới phát hiện ra cách kết hợp các phần tốt nhất của bash và ipython. Cho đến bây giờ điều này có vẻ thoải mái với tôi hơn là sử dụng quy trình con, v.v. Bạn có thể dễ dàng sao chép các phần lớn của tập lệnh bash hiện có và ví dụ: thêm xử lý lỗi theo cách python :) Và đây là kết quả của tôi:

#!/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 ;)

Xem tài liệu IPython trên các lệnh shell hệ thống và sử dụng nó làm shell hệ thống .


11
Được khuyến khích bởi vì một số lý do kỳ quái, không ai khác đã đề cập! -Các lệnh trong IPython, đó là khóa hoàn toàn; đặc biệt là vì bạn cũng có thể gán đầu ra của chúng cho một biến (danh sách các dòng) như trongfilelines = ! cat myfile
kampu

Và bạn có thể sử dụng biến python như $vartrong lệnh shell? Ồ Đây phải là câu trả lời được chấp nhận.
Chiel ten Brinke

Và bạn cũng có thể sử dụng nó từ trong sổ ghi chép của jupyter
Yuval Atzmon

44

Kể từ năm 2015 và phiên bản Python 3.4, giờ đây đã có một vỏ tương tác người dùng hoàn chỉnh hợp lý có sẵn tại: http://xon.sh/ hoặc https://github.com/scopatz/xonsh

Video trình diễn không hiển thị các đường ống đang được sử dụng, nhưng chúng được hỗ trợ khi ở chế độ vỏ mặc định.

Xonsh ('conch') rất cố gắng để mô phỏng bash, vì vậy những thứ bạn đã có được bộ nhớ cơ bắp, như

env | uniq | sort -r | grep PATH

hoặc là

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

vẫn sẽ hoạt động tốt

Hướng dẫn này khá dài và dường như bao gồm một lượng đáng kể các chức năng mà ai đó thường mong đợi ở dấu nhắc tro hoặc bash:

  • Biên dịch, Đánh giá và Thực thi!
  • Lịch sử lệnh và hoàn thành tab
  • Trợ giúp & Siêu nhân với ?&??
  • Bí danh & Lời nhắc tùy chỉnh
  • Thực thi các lệnh và / hoặc *.xshtập lệnh cũng có thể được nhập
  • Biến môi trường bao gồm Tra cứu với ${}
  • Kết hợp đầu vào / đầu ra và kết hợp
  • Bối cảnh công việc & kiểm soát công việc
  • Các quy trình lồng nhau, ống và đồng xử lý
  • Chế độ con khi chế độ tồn tại lệnh, chế độ Python khác
  • Các quy trình đã chụp với $(), Quy trình chưa được xử lý với $[], Đánh giá Python với@()
  • Tên tệp Globbing với *hoặc Biểu thức thông thường Tên tệp Globbing với Backticks

Nhưng tại sao có vẻ như tất cả các câu trả lời này chỉ là phát minh lại bánh xe cho những người không biết bash ? Tôi đã nhận được sự thoải mái vừa phải với bash và mỗi một trong những câu trả lời này có vẻ như nó sẽ trở thành công việc nhiều hơn vì lợi ích nhỏ. Những câu trả lời này đều nhắm đến những người trăn sợ (hoặc không muốn dành thời gian học) bash, phải không?
Butussy Butkus

Có vẻ như nó có một số nhược điểm như yêu cầu sử dụng .xshtiện ích mở rộng cho các tệp có mã xonsh: github.com/xonsh/xonsh/issues/2478 . Nếu không, bạn phải sử dụng evalxđể gọi nó trực tiếp từ các .pytập tin.
Andry

31
  • Nếu bạn muốn sử dụng Python làm shell, tại sao không xem qua IPython ? Nó cũng tốt để học tương tác ngôn ngữ.
  • Nếu bạn thực hiện nhiều thao tác văn bản và nếu bạn sử dụng Vim làm trình soạn thảo văn bản, bạn cũng có thể trực tiếp viết plugin cho Vim bằng python. chỉ cần gõ ": help python" trong Vim và làm theo hướng dẫn hoặc xem phần trình bày này . Thật dễ dàng và mạnh mẽ để viết các chức năng mà bạn sẽ sử dụng trực tiếp trong trình soạn thảo của mình!

8
có một hồ sơ ipython được gọi là 'sh' làm cho trình thông dịch rất giống một cái vỏ.
Autoplectic

3
Hồ sơ ipython 'sh' đã bị xóa một thời gian.
gdw2

>>> kết quả =! dmesg | grep -i 'usb' #the! nhà điều hành làm tất cả
Permafacture

16

Lúc đầu, có sh, sed và awk (và tìm, và grep, và ...). Thật tốt Nhưng awk có thể là một con thú nhỏ kỳ lạ và khó nhớ nếu bạn không sử dụng nó thường xuyên. Sau đó, con lạc đà vĩ đại đã tạo ra Perl. Perl là giấc mơ của quản trị viên hệ thống. Nó giống như kịch bản shell trên steroid. Xử lý văn bản, bao gồm các biểu thức thông thường chỉ là một phần của ngôn ngữ. Sau đó, nó trở nên xấu xí ... Mọi người đã cố gắng tạo ra các ứng dụng lớn với Perl. Bây giờ, đừng hiểu sai ý tôi, Perl có thể là một ứng dụng, nhưng nó có thể (có thể!) Trông như một mớ hỗn độn nếu bạn không thực sự cẩn thận. Sau đó, có tất cả kinh doanh dữ liệu phẳng này. Nó đủ để lái một lập trình viên.

Nhập Python, Ruby, et al. Đây là những ngôn ngữ có mục đích chung rất tốt. Họ hỗ trợ xử lý văn bản và làm tốt điều đó (mặc dù có lẽ không gắn chặt với cốt lõi cơ bản của ngôn ngữ). Nhưng họ cũng mở rộng quy mô rất tốt, và vẫn có mã nhìn đẹp vào cuối ngày. Họ cũng đã phát triển các cộng đồng khá lớn với nhiều thư viện cho hầu hết mọi thứ.

Bây giờ, phần lớn sự tiêu cực đối với Perl là vấn đề quan điểm, và chắc chắn một số người có thể viết Perl rất sạch sẽ, nhưng với điều này, nhiều người phàn nàn về việc quá dễ dàng để tạo ra mã bị che giấu, bạn biết một số sự thật là có. Câu hỏi thực sự trở thành sau đó, bạn có bao giờ sử dụng ngôn ngữ này cho nhiều thay thế tập lệnh bash đơn giản. Nếu không, tìm hiểu thêm một số Perl .. nó hoàn toàn tuyệt vời cho điều đó. Mặt khác, nếu bạn muốn có một ngôn ngữ sẽ phát triển cùng với bạn khi bạn muốn làm nhiều hơn, tôi có thể đề xuất Python hoặc Ruby.

Dù bằng cách nào, chúc may mắn!


9

Tôi đề nghị cuốn sách trực tuyến tuyệt vời Lặn vào Python . Đó là cách tôi học ngôn ngữ ban đầu.

Ngoài việc dạy cho bạn cấu trúc cơ bản của ngôn ngữ và rất nhiều cấu trúc dữ liệu hữu ích, nó có một chương tốt về xử lý tệp và các chương tiếp theo về biểu thức chính quy và hơn thế nữa.


1
... vấn đề chính của câu trả lời chỉ liên kết.
Jean-François Fabre


7

Một lý do tôi yêu Python là nó được chuẩn hóa tốt hơn nhiều so với các công cụ POSIX. Tôi phải kiểm tra gấp đôi và gấp ba rằng mỗi bit có tương thích với các hệ điều hành khác không. Một chương trình được viết trên hệ thống Linux có thể không hoạt động giống nhau trên hệ thống BSD của OSX. Với Python, tôi chỉ cần kiểm tra xem hệ thống đích có phiên bản Python đủ hiện đại không.

Thậm chí tốt hơn, một chương trình được viết bằng Python chuẩn thậm chí sẽ chạy trên Windows!


1
"một chương trình được viết bằng Python chuẩn thậm chí sẽ chạy trên Windows": không đùa đâu?
Jean-François Fabre

6

Tôi sẽ đưa ra ý kiến ​​của mình dựa trên kinh nghiệm:

Đối với vỏ:

  • Shell có thể rất dễ dàng sinh ra mã chỉ đọc. Viết nó và khi bạn quay lại với nó, bạn sẽ không bao giờ tìm ra những gì bạn đã làm một lần nữa. Rất dễ dàng để thực hiện điều này.
  • shell có thể thực hiện RẤT NHIỀU xử lý văn bản, phân tách, vv trong một dòng với các đường ống.
  • nó là ngôn ngữ keo tốt nhất khi tích hợp cuộc gọi của các chương trình trong các ngôn ngữ lập trình khác nhau.

Đối với trăn:

  • nếu bạn muốn tính di động cho các cửa sổ đi kèm, hãy sử dụng python.
  • python có thể tốt hơn khi bạn phải thao tác nhiều hơn văn bản, chẳng hạn như bộ sưu tập số. Đối với điều này, tôi đề nghị python.

Tôi thường chọn bash cho hầu hết mọi thứ, nhưng khi tôi có thứ gì đó phải vượt qua ranh giới cửa sổ, tôi chỉ sử dụng python.


4

pythonpy là một công cụ cung cấp quyền truy cập dễ dàng vào nhiều tính năng từ awk và sed, nhưng sử dụng cú pháp python:

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

3

Tôi đã xây dựng các tập lệnh shell bán dài (300-500 dòng) và mã Python có chức năng tương tự. Khi nhiều lệnh bên ngoài đang được thực thi, tôi thấy shell dễ sử dụng hơn. Perl cũng là một lựa chọn tốt khi có nhiều thao tác văn bản.


3

Trong khi nghiên cứu chủ đề này, tôi đã tìm thấy mã bằng chứng khái niệm này (thông qua một nhận xét tại http://jlebar.com/2010/2/1/Replaces_Bash.html ) cho phép bạn "viết các đường ống giống như vỏ sò trong Python bằng cách sử dụng cú pháp ngắn gọn và tận dụng các công cụ hệ thống hiện có nơi chúng có ý nghĩa ":

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

2

Đặt cược tốt nhất của bạn là một công cụ dành riêng cho vấn đề của bạn. Nếu nó đang xử lý các tệp văn bản, thì Sed, Awk và Perl là những ứng cử viên hàng đầu. Python là một ngôn ngữ năng động có mục đích chung . Như với bất kỳ ngôn ngữ mục đích chung nào, có hỗ trợ cho thao tác tệp, nhưng đó không phải là mục đích cốt lõi của nó. Tôi sẽ xem xét Python hoặc Ruby nếu tôi có yêu cầu về ngôn ngữ động nói riêng.

Nói tóm lại, hãy tìm hiểu kỹ về Sed và Awk, cộng với tất cả những điều tốt đẹp khác đi kèm với hương vị * nix của bạn (Tất cả các Bash dựng sẵn, grep, tr và vv). Nếu đó là xử lý tệp văn bản mà bạn quan tâm, bạn đã sử dụng đúng nội dung.


2

Bạn có thể sử dụng python thay vì bash với thư viện ShellPy .

Dưới đây là một ví dụ tải xuống hình đại diện của người dùng Python từ 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')

Như bạn có thể thấy, tất cả các biểu thức bên trong biểu tượng dấu trọng âm (`) được thực thi trong shell. Và trong mã Python, bạn có thể nắm bắt kết quả của việc thực hiện này và thực hiện các hành động trên nó. Ví dụ:

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

Dòng này trước tiên sẽ thực thi git log --pretty=oneline --grep='Create'trong shell và sau đó gán kết quả cho biến log. Kết quả có các thuộc tính sau:

stdout toàn bộ văn bản từ stdout của quá trình thực hiện

stderr toàn bộ văn bản từ stderr của quá trình thực hiện

returncode returncode của thực thi

Đây là tổng quan chung của thư viện, mô tả chi tiết hơn với các ví dụ có thể được tìm thấy ở đây .


1

Nếu thao tác xử lý tệp văn bản của bạn thường là một lần, có thể được thực hiện trên dấu nhắc shell, bạn sẽ không nhận được gì tốt hơn từ python.

Mặt khác, nếu bạn thường xuyên phải thực hiện cùng một nhiệm vụ (hoặc tương tự), và bạn phải viết các tập lệnh của mình để làm điều đó, thì python rất tuyệt - và bạn có thể dễ dàng tạo thư viện của riêng mình (bạn có thể làm điều đó với các kịch bản shell cũng vậy, nhưng nó cồng kềnh hơn).

Một ví dụ rất đơn giản để có được một cảm giác.

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

Kiểm tra cả sys và mô-đun getopt, chúng là đầu tiên bạn sẽ cần.


1

Tôi đã xuất bản một gói trên PyPI: ez .
Sử dụng pip install ezđể cài đặt nó.

Nó đã đóng gói các lệnh phổ biến trong shell và độc đáo lib của tôi sử dụng cú pháp cơ bản giống như shell. ví dụ: cp (nguồn, đích) có thể xử lý cả tệp và thư mục! (trình bao bọc của shutil.copy shutil.copytree và nó quyết định khi nào nên sử dụng cái nào). Thậm chí độc đáo hơn, nó có thể hỗ trợ vector hóa như R!

Một ví dụ khác: không có os.walk, sử dụng fls (path, regex) để tìm đệ quy các tệp và bộ lọc với biểu thức chính quy và nó trả về một danh sách các tệp có hoặc không có fullpath

Ví dụ cuối cùng: bạn có thể kết hợp chúng để viết các tập lệnh rất đơn giản:
files = fls('.','py$'); cp(files, myDir)

Chắc chắn kiểm tra xem nó ra! Tôi đã mất hàng trăm giờ để viết / cải thiện nó!


1
Trông có vẻ thú vị, nhưng tôi không thể vượt qua các tài liệu chưa được định dạng tại pypi.python.org/pypi/ez , xin lỗi ...
Greg Dubicki
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.