ขณะนี้ฉันทำการจัดการไฟล์ข้อความผ่าน AWK, sed, Bash และ Perl นิด ๆ
ฉันเคยเห็นพูดถึงสถานที่บางแห่งที่หลามดีสำหรับสิ่งนี้ ฉันจะใช้ Python เพื่อแทนที่ shell scripting, AWK, sed และ Friends ได้อย่างไร
ขณะนี้ฉันทำการจัดการไฟล์ข้อความผ่าน AWK, sed, Bash และ Perl นิด ๆ
ฉันเคยเห็นพูดถึงสถานที่บางแห่งที่หลามดีสำหรับสิ่งนี้ ฉันจะใช้ Python เพื่อแทนที่ shell scripting, AWK, sed และ Friends ได้อย่างไร
คำตอบ:
เชลล์ใด ๆ มีคุณสมบัติหลายชุด
คำสั่ง Essential Linux / Unix ทั้งหมดนี้มีอยู่ในไลบรารีย่อย นี่ไม่ใช่ตัวเลือกแรกที่ดีที่สุดสำหรับการทำคำสั่งภายนอกทั้งหมด ดูที่Shutilสำหรับคำสั่งบางคำซึ่งเป็นคำสั่ง Linux แยกกัน แต่คุณอาจนำไปใช้โดยตรงในสคริปต์ Python ของคุณ อีกชุดคำสั่ง Linux ขนาดใหญ่อยู่ในไลบรารีระบบปฏิบัติการ คุณสามารถทำสิ่งเหล่านี้ได้ง่ายขึ้นใน Python
และ - โบนัส! -- เร็วกว่านี้. แต่ละคำสั่ง Linux ที่แยกต่างหากในเชลล์ (โดยมีข้อยกเว้นเล็กน้อย) จะระงับกระบวนการย่อย โดยใช้ Python shutil
และos
โมดูลคุณจะไม่แยกกระบวนการย่อย
คุณสมบัติสภาพแวดล้อมของเชลล์ ซึ่งรวมถึงสิ่งต่าง ๆ ที่ตั้งค่าสภาพแวดล้อมของคำสั่ง (ไดเรกทอรีปัจจุบันและตัวแปรสภาพแวดล้อมและสิ่งที่ไม่ใช่) คุณสามารถจัดการสิ่งนี้ได้จาก Python โดยตรง
คุณสมบัติการเขียนโปรแกรมเชลล์ นี่คือการตรวจสอบรหัสสถานะกระบวนการทั้งหมดคำสั่งตรรกะต่างๆ (ถ้าในขณะสำหรับ ฯลฯ ) คำสั่งทดสอบและญาติทั้งหมด สิ่งที่นิยามฟังก์ชั่น นี่คือทั้งหมดที่มากขึ้นง่ายขึ้นใน Python นี่เป็นหนึ่งในชัยชนะอันยิ่งใหญ่ในการกำจัดทุบตีและทำมันใน Python
คุณสมบัติการโต้ตอบ ซึ่งรวมถึงประวัติคำสั่งและสิ่งที่ไม่ คุณไม่ต้องการสิ่งนี้สำหรับการเขียนเชลล์สคริปต์ สิ่งนี้มีไว้สำหรับการโต้ตอบของมนุษย์เท่านั้นไม่ใช่สำหรับการเขียนสคริปต์
คุณสมบัติการจัดการไฟล์เชลล์ ซึ่งรวมถึงการเปลี่ยนเส้นทางและไปป์ไลน์ นี่มันช่างเขินนะ สิ่งเหล่านี้สามารถทำได้ด้วยกระบวนการย่อย แต่บางสิ่งที่เปลือกหอยง่ายใน Python (a | b; c ) | something >result
โดยเฉพาะสิ่งที่ชอบ สิ่งนี้จะทำงานสองกระบวนการในแบบคู่ขนาน (โดยมีเอาต์พุตa
เป็นอินพุตไปยังb
) ตามด้วยกระบวนการที่สาม เอาท์พุทจากลำดับที่จะดำเนินการควบคู่ไปกับการและการส่งออกจะถูกรวบรวมเป็นไฟล์ที่ชื่อว่าsomething
result
มันซับซ้อนมากที่จะแสดงเป็นภาษาอื่น
โปรแกรมเฉพาะ (awk, sed, grep และอื่น ๆ ) สามารถเขียนใหม่เป็นโมดูล Python อย่าไปลงน้ำ แทนที่สิ่งที่คุณต้องการและพัฒนาโมดูล "grep" ของคุณ อย่าเริ่มเขียนโมดูล Python ที่แทนที่ "grep"
สิ่งที่ดีที่สุดคือคุณสามารถทำได้ในขั้นตอน
os.walk
กับงูหลามลูปการใช้งานที่ นี่เป็นชัยชนะครั้งใหญ่เพราะคุณไม่ได้วางไข่เป็นจำนวนมากfind
สคริปต์หลายตัวที่ฉันมีนั้นน่าเกลียดและยาวและไม่สามารถเปรียบเทียบได้ หลายสิ่งหลายอย่างที่ควรจะเป็นเชลล์สคริปต์อื่น ๆ อีกมากมายไม่ควร ไม่ใช่ทุกสิ่งที่จำเป็นต้องเป็นเพียงหนึ่งใน Python หรือ BASH (หรืออย่างอื่น)
(a | b; c ) | something >result
) ค่อนข้างบรรเทาโดยมันง่ายนิดเดียวผ่านเปลือกท่อไปยังsubprocess
วิธีการใช้shell=True
ใช่แน่นอน :)
ลองดูไลบรารี่เหล่านี้ซึ่งจะช่วยให้คุณไม่ต้องเขียนเชลล์สคริปต์อีกครั้ง (คำขวัญของ Plumbum)
นอกจากนี้หากคุณต้องการแทนที่ awk, sed และ grep ด้วย Python ตามสิ่งที่ฉันแนะนำpyp -
"The Pyed Piper" หรือ pyp เป็นเครื่องมือจัดการข้อความบนบรรทัดคำสั่ง linux ซึ่งคล้ายกับ awk หรือ sed แต่ใช้สตริงไพ ธ อนมาตรฐานและรายการวิธีการเช่นเดียวกับฟังก์ชั่นที่กำหนดเองที่พัฒนาเพื่อสร้างผลลัพธ์ที่รวดเร็วในสภาพแวดล้อมการผลิตที่เข้มข้น
ฉันเพิ่งค้นพบวิธีการรวมส่วนที่ดีที่สุดของ bash และ ipython ถึงตอนนี้ฉันรู้สึกสบายใจกว่าใช้ subprocess และอื่น ๆ คุณสามารถคัดลอกส่วนใหญ่ของสคริปต์ทุบตีที่มีอยู่และเช่นเพิ่มการจัดการข้อผิดพลาดด้วยวิธีหลาม :) และนี่คือผลลัพธ์ของฉัน:
#!/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 ;)
ดูเอกสาร IPython ในคำสั่งเชลล์ระบบและใช้มันเป็นเปลือกระบบ
filelines = ! cat myfile
$var
ในคำสั่งเชลล์ได้หรือไม่ ว้าว. นี่ควรเป็นคำตอบที่ยอมรับได้
ตั้งแต่ปี 2015 และ Python 3.4 มีตอนนี้เชลล์แบบอินเทอร์แอคทีฟที่สมบูรณ์ที่ผู้ใช้สามารถดูได้ที่: http://xon.sh/หรือhttps://github.com/scopatz/xonsh
วิดีโอสาธิตไม่แสดงท่อถูกนำมาใช้ แต่พวกเขาได้รับการสนับสนุนเมื่ออยู่ในโหมดเปลือกเริ่มต้น
Xonsh ('conch') พยายามอย่างหนักที่จะเลียนแบบทุบตีดังนั้นสิ่งที่คุณได้รับความทรงจำของกล้ามเนื้อเช่นนั้น
env | uniq | sort -r | grep PATH
หรือ
my-web-server 2>&1 | my-log-sorter
จะยังคงทำงานได้ดี
การสอนมีความยาวมากและดูเหมือนจะครอบคลุมการใช้งานที่คนทั่วไปคาดหวังในระดับขี้เถ้าหรือทุบตี:
?
&??
*.xsh
สคริปต์ซึ่งสามารถนำเข้าได้${}
$()
, uncaptured subprocess กับ$[]
, การประเมินผลของ Python ด้วย@()
*
หรือนิพจน์ปกติชื่อไฟล์ Globbing กับ Backticks.xsh
ส่วนขยายสำหรับไฟล์ที่มีรหัส xonsh นี้: github.com/xonsh/xonsh/issues/2478 มิฉะนั้นคุณต้องใช้evalx
เพื่อโทรโดยตรงจาก.py
ไฟล์
ในตอนแรกมี sh, sed และ awk (และค้นหาและ grep และ ... ) มันดีนะ. แต่ awk อาจเป็นสัตว์ประหลาดตัวเล็ก ๆ และจำได้ยากหากคุณไม่ได้ใช้บ่อย จากนั้นอูฐผู้ยิ่งใหญ่ก็สร้าง Perl ขึ้น Perl เป็นความฝันของผู้ดูแลระบบ มันเหมือนกับการเขียนสคริปต์เชลล์บนเตียรอยด์ การประมวลผลข้อความรวมถึงนิพจน์ทั่วไปเป็นเพียงส่วนหนึ่งของภาษา จากนั้นมันก็น่าเกลียด ... ผู้คนพยายามสร้างแอพพลิเคชั่นขนาดใหญ่ด้วย Perl ตอนนี้อย่าเข้าใจฉันผิด Perl สามารถเป็นแอปพลิเคชันได้ แต่มันสามารถ (สามารถ!) ดูเหมือนเป็นระเบียบถ้าคุณไม่ระวังจริงๆ จากนั้นก็มีธุรกิจดาต้าแบนนี้ทั้งหมด มันเพียงพอแล้วที่จะผลักดันโปรแกรมเมอร์
ป้อน Python, Ruby และอื่น ๆ เหล่านี้เป็นภาษาวัตถุประสงค์ทั่วไปที่ดีมากจริงๆ พวกเขาสนับสนุนการประมวลผลข้อความและทำมันได้ดี (แม้ว่าอาจจะไม่ได้ผูกมัดอย่างแน่นหนาในหลักพื้นฐานของภาษา) แต่พวกเขาก็ขยายขนาดได้ดีมากและยังคงมีโค้ดที่ดูดีในตอนท้ายของวัน พวกเขายังได้พัฒนาชุมชนที่ค่อนข้างแข็งแรงพร้อมห้องสมุดมากมายสำหรับทุกสิ่ง
ตอนนี้การปฏิเสธต่อ Perl ส่วนใหญ่เป็นเรื่องของความเห็นและแน่นอนว่าบางคนสามารถเขียน Perl ที่สะอาดมาก แต่ด้วยคนจำนวนมากที่บ่นว่ามันง่ายเกินไปที่จะสร้างรหัสที่สับสนคุณรู้ว่าความจริงบางอย่างอยู่ที่นั่น คำถามจะกลายเป็นจริงคุณจะเคยใช้ภาษานี้มานานกว่าการเปลี่ยนสคริปต์ทุบตีง่าย ๆ ถ้าไม่เรียนรู้เพิ่มเติม Perl .. มันยอดเยี่ยมอย่างแน่นอนสำหรับที่ ในทางกลับกันถ้าคุณต้องการภาษาที่จะเติบโตไปพร้อมกับคุณตามที่คุณต้องการมากขึ้นฉันขอแนะนำ Python หรือ Ruby
โชคดี!
ผมขอแนะนำหนังสือออนไลน์ที่น่ากลัวดำน้ำลงในหลาม มันเป็นวิธีที่ฉันเรียนรู้ภาษาเดิม
นอกเหนือจากการสอนโครงสร้างพื้นฐานของภาษาและโครงสร้างข้อมูลที่มีประโยชน์มากมายมันมีบทที่ดีเกี่ยวกับการจัดการไฟล์และบทต่อ ๆ มาในการแสดงออกปกติและอื่น ๆ
การเพิ่มคำตอบก่อนหน้า: ตรวจสอบโมดูลpexpectสำหรับจัดการกับคำสั่งแบบโต้ตอบ (adduser, passwd เป็นต้น)
เหตุผลหนึ่งที่ฉันชอบ Python ก็คือมันเป็นมาตรฐานที่ดีกว่าเครื่องมือ POSIX ฉันต้องตรวจสอบสองครั้งและสามครั้งว่าแต่ละบิตเข้ากันได้กับระบบปฏิบัติการอื่น โปรแกรมที่เขียนบนระบบ Linux อาจไม่ทำงานเหมือนกันในระบบ BSD ของ OSX ด้วย Python ฉันแค่ต้องตรวจสอบว่าระบบเป้าหมายมี Python เวอร์ชันที่ทันสมัยเพียงพอแล้ว
ยิ่งไปกว่านั้นโปรแกรมที่เขียนใน Python มาตรฐานจะทำงานบน Windows!
ฉันจะให้ความเห็นที่นี่ตามประสบการณ์:
สำหรับเปลือก:
สำหรับงูหลาม:
ฉันมักจะเลือกทุบตีเพื่อสิ่งต่าง ๆ ส่วนใหญ่ แต่เมื่อฉันมีบางอย่างที่ต้องข้ามขอบเขตหน้าต่างฉันก็ใช้หลาม
pythonpyเป็นเครื่องมือที่ให้การเข้าถึงคุณลักษณะหลายอย่างจาก awk และ sed แต่ใช้ไวยากรณ์ของ python:
$ echo me2 | py -x 're.sub("me", "you", x)'
you2
ฉันได้สร้างเชลล์สคริปต์แบบกึ่งยาว (300-500 บรรทัด) และรหัส Python ซึ่งทำหน้าที่คล้ายกัน เมื่อคำสั่งภายนอกจำนวนมากถูกดำเนินการฉันพบว่า shell นั้นใช้งานง่ายกว่า Perl ยังเป็นตัวเลือกที่ดีเมื่อมีการจัดการข้อความจำนวนมาก
ในขณะที่ค้นคว้าหัวข้อนี้ฉันพบรหัสการพิสูจน์แนวคิดนี้ (ผ่านความคิดเห็นที่http://jlebar.com/2010/2/1/Replacing_Bash.html ) ที่ให้คุณ "เขียนท่อเหมือนเชลล์ใน Python โดยใช้ ไวยากรณ์ของคำศัพท์สั้น ๆ และใช้ประโยชน์จากเครื่องมือระบบที่มีอยู่แล้ว
for line in sh("cat /tmp/junk2") | cut(d=',',f=1) | 'sort' | uniq:
sys.stdout.write(line)
ทางออกที่ดีที่สุดของคุณคือเครื่องมือที่มุ่งเน้นที่ปัญหาของคุณโดยเฉพาะ หากเป็นการประมวลผลไฟล์ข้อความ Sed, Awk และ Perl จะเป็นอันดับต้น ๆ Python เป็นภาษาไดนามิกที่ใช้งานทั่วไป เช่นเดียวกับภาษาวัตถุประสงค์ทั่วไปมีการรองรับการจัดการไฟล์ แต่นั่นไม่ใช่สิ่งที่เป็นวัตถุประสงค์หลัก ฉันจะพิจารณา Python หรือ Ruby ถ้าฉันมีข้อกำหนดสำหรับภาษาไดนามิกโดยเฉพาะ
ในระยะสั้นเรียนรู้ Sed และ Awk ได้ดีจริงๆรวมทั้งสินค้าอื่น ๆ ทั้งหมดที่มาพร้อมกับรสชาติของ * nix (Bash ในตัวทั้งหมด, grep, tr และอื่น ๆ ) หากเป็นการประมวลผลไฟล์ข้อความที่คุณสนใจแสดงว่าคุณใช้สิ่งที่ถูกต้องอยู่แล้ว
คุณสามารถใช้หลามแทนการทุบตีด้วยShellPyห้องสมุด
นี่คือตัวอย่างที่ดาวน์โหลดอวตารของผู้ใช้ Python จาก 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')
อย่างที่คุณเห็นสัญลักษณ์ทั้งหมดที่อยู่ในสัญลักษณ์สำเนียงหลุมฝังศพ (`) ถูกเรียกใช้ในเชลล์ และในรหัสไพ ธ อนคุณสามารถบันทึกผลลัพธ์ของการดำเนินการนี้และดำเนินการกับมันได้ ตัวอย่างเช่น:
log = `git log --pretty=oneline --grep='Create'
บรรทัดนี้จะเรียกใช้งานgit log --pretty=oneline --grep='Create'
ในเชลล์ก่อนจากนั้นจึงกำหนดผลลัพธ์ให้กับตัวแปรบันทึก ผลลัพธ์มีคุณสมบัติดังต่อไปนี้:
stdoutข้อความทั้งหมดจาก stdout ของกระบวนการดำเนินการ
stderrข้อความทั้งหมดจาก stderr ของกระบวนการที่ดำเนินการ
returncode returncode ของการดำเนินการ
นี่คือภาพรวมทั่วไปของห้องสมุดรายละเอียดเพิ่มเติมเกี่ยวกับตัวอย่างที่สามารถพบได้ที่นี่
หากการจัดการ textfile ของคุณเป็นแบบครั้งเดียวอาจทำได้บน shell-prompt คุณจะไม่ได้อะไรที่ดีกว่าจากไพ ธ อน
ในทางกลับกันถ้าคุณมักจะต้องทำภารกิจเดียวกัน (หรือคล้ายกัน) ซ้ำแล้วซ้ำอีกและคุณต้องเขียนสคริปต์ของคุณสำหรับการทำเช่นนั้นงูหลามนั้นยอดเยี่ยม - และคุณสามารถสร้างห้องสมุดของคุณเองได้อย่างง่ายดาย มีเชลล์สคริปต์ด้วย แต่ก็ยุ่งยากกว่า)
ตัวอย่างง่ายๆที่ให้ความรู้สึก
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
ตรวจสอบโมดูล sys และ getopt พวกเขาเป็นคนแรกที่คุณจะต้อง
ฉันได้เผยแพร่แพ็คเกจบน PyPI: ezแล้ว
ใช้pip install ez
สำหรับติดตั้ง
มันบรรจุคำสั่งทั่วไปในเชลล์และ lib ของฉันใช้ไวยากรณ์เดียวกับเชลล์ เช่น cp (ต้นทางปลายทาง) สามารถจัดการได้ทั้งไฟล์และโฟลเดอร์! (wrapper ของ shutil.copy shutil.copytree และจะตัดสินใจว่าจะใช้เมื่อใด) ยิ่งไปกว่านั้นมันสามารถรองรับ vectorization เช่น R!
อีกตัวอย่าง: ไม่มี os.walk ใช้ fls (path, regex) เพื่อค้นหาไฟล์และตัวกรองซ้ำด้วยนิพจน์ทั่วไปและส่งคืนรายการไฟล์ที่มีหรือไม่มีพา ธ เต็ม
ตัวอย่างสุดท้าย: คุณสามารถรวมไว้เพื่อเขียนสคริปต์อย่างง่าย ๆ :
files = fls('.','py$'); cp(files, myDir)
ตรวจสอบอย่างแน่นอน! มีค่าใช้จ่ายฉันหลายร้อยชั่วโมงในการเขียน / ปรับปรุง!