ฉันจะเขียนตัวกรอง unix ใน python ได้อย่างไร

ฉันต้องการเขียนโปรแกรมที่อ่าน stdin (ไม่มีบัฟเฟอร์) และเขียน stdout (ไม่มีบัฟเฟอร์) โดยทำการแปลงถ่านต่อถ่านเล็กน้อย เพื่อประโยชน์ของตัวอย่าง สมมติว่าฉันต้องการลบตัวอักษรทั้งหมด x ออกจาก stdin


person flybywire    schedule 19.10.2009    source แหล่งที่มา


คำตอบ (4)


ฉันไม่รู้ว่าคุณหมายถึงอะไรโดยบัฟเฟอร์ในบริบทนี้ แต่มันค่อนข้างง่ายที่จะทำสิ่งที่คุณถาม ...

so_gen.py (สร้างกระแสคงที่ที่เราสามารถรับชมได้):

import time
import sys
while True:
    for char in 'abcdefx':
        sys.stdout.write(char)
        sys.stdout.flush()
        time.sleep(0.1)

so_filter.py (ทำสิ่งที่คุณถาม):

import sys
while True:
    char = sys.stdin.read(1)
    if not char:
        break
    if char != 'x':
        sys.stdout.write(char)
        sys.stdout.flush()

ลองเรียกใช้ python so_gen.py | python so_filter.py เพื่อดูว่ามันทำอะไร

person Mike Boers    schedule 19.10.2009
comment
ผู้ชนะในการเขียน if not char: break - person flybywire; 19.10.2009

อ่านจาก sys.stdin และเขียนถึง sys.stdout (หรือใช้ print) โปรแกรมตัวอย่างของคุณ:

import sys

for line in sys.stdin:
    print line.replace("x", ""),

ไม่มีวิธีมาตรฐานในการทำให้ stdin ไม่มีบัฟเฟอร์และคุณไม่ต้องการสิ่งนั้น ปล่อยให้ OS บัฟเฟอร์มัน

person Jed Smith    schedule 19.10.2009
comment
เขาบอกว่าไม่มีบัฟเฟอร์ แต่ฉันไม่แน่ใจว่ามันสำคัญจริงๆ - person Chris Lutz; 19.10.2009

คุณสามารถใช้ fileinput class ซึ่งช่วยให้คุณประมวลผลอินพุตได้เหมือนกับที่ตัวดำเนินการเพชร Perl ทำ จากเอกสาร:

import fileinput
for line in fileinput.input():
    process(line)

โดยที่กระบวนการทำอะไรบางอย่างเช่น print line.replace('x','')

คุณสามารถติดตามคำถาม StackOverflow นี้ สำหรับวิธีปลดบัฟเฟอร์ stdout หรือคุณสามารถโทร sys.stdout.flush() หลังจากแต่ละ print

person Emil Sit    schedule 19.10.2009
comment
อา! สิ่งนี้ทำให้งานพิเศษทั้งหมดที่ฉันทำเพราะฉันพลาด Perl ไปโดยเปล่าประโยชน์! ฉันต้องผ่านไลบรารีมาตรฐาน Python อย่างใกล้ชิด - person Chris Lutz; 19.10.2009
comment
นี่ควรเป็นคำตอบที่ยอมรับได้ โมดูล fileinput ถูกสร้างขึ้นมาสำหรับกรณีการใช้งานนี้ทุกประการ - person Antoine Gallix; 03.06.2019

ใช้สวิตช์ -u สำหรับล่ามหลามเพื่อทำให้การอ่านและเขียนทั้งหมดไม่มีบัฟเฟอร์ คล้ายกับการตั้งค่า $| = true; ใน Perl จากนั้นดำเนินการตามที่คุณต้องการ โดยอ่านบรรทัดที่แก้ไขแล้วจึงพิมพ์ sys.stdout.flush() ไม่จำเป็นต้องใช้

#!/path/to/python -u

import sys

for line in sys.stdin:
    process_line(line)
person EmFi    schedule 19.10.2009