আমি কীভাবে পাইথন প্রোগ্রামগুলি যথাযথ ইউনিক্স সরঞ্জামগুলির মতো আচরণ করব?


24

আমার কয়েকটি পাইথনের স্ক্রিপ্ট রয়েছে যার চারপাশে রয়েছে এবং আমি সেগুলি পুনর্লিখনের কাজ করছি। আমার সবার সাথে একই সমস্যা আছে।

প্রোগ্রামগুলি কীভাবে লিখবেন তা আমার কাছে স্পষ্ট নয় যাতে তারা যথাযথ ইউনিক্স সরঞ্জামগুলির মতো আচরণ করে।

কারণ এই

$ cat characters | progname

এবং এই

$ progname characters

একই আউটপুট উত্পাদন করা উচিত।

পাইথনে আমি যে নিকটতম জিনিসটি দেখতে পেতাম তা হ'ল ফাইল ইনপুট লাইব্রেরি। দুর্ভাগ্যক্রমে, আমি আমার পাইথন স্ক্রিপ্টগুলি কীভাবে পুনরায় লেখতে পারি তা সত্যই দেখতে পাচ্ছি না, সবগুলিই এর মতো দেখাচ্ছে:

#!/usr/bin/env python 
# coding=UTF-8

import sys, re

for file in sys.argv[1:]:
    f = open(file)
    fs = f.read()
    regexnl = re.compile('[^\s\w.,?!:;-]')
    rstuff = regexnl.sub('', fs)
    f.close()
    print rstuff

স্টিডিন থাকলে ফাইলিনপুট লাইব্রেরি স্টিডিন প্রক্রিয়াজাত করে এবং একটি ফাইল থাকলে কোনও ফাইল প্রসেস করে। তবে এটি একক লাইনে পুনরাবৃত্তি করে।

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

আমি সত্যিই তা পাই না। আমার ধারণা আপনি যদি ছোট ফাইলগুলি নিয়ে কাজ করছেন বা আপনি যদি ফাইলগুলিতে বেশি কিছু না করেন তবে এটি স্পষ্ট বলে মনে হতে পারে। তবে, আমার উদ্দেশ্যগুলির জন্য, এটি পুরো ফাইলটি খোলার এবং উপরে স্ট্রিংয়ের মধ্যে স্ট্রিংয়ে পড়ার চেয়ে অনেক ধীর করে তোলে।

বর্তমানে আমি উপরের স্ক্রিপ্টটি চালাচ্ছি

$ pythonscript textfilename1 > textfilename2

তবে আমি এটি (এবং এর ভাইয়েরা) পাইপের মতো চালাতে সক্ষম হতে চাই

$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2

উত্তর:


9

শুধু না কেন

files = sys.argv[1:]
if not files:
    files = ["/dev/stdin"]

for file in files:
    f = open(file)
    ...

12
sys.stdinপরিবর্তে এটি ফাইলের হার্ডকোডযুক্ত পথের চেয়ে পোর্টেবল হিসাবে ব্যবহার করা উচিত।
পাইটর ডব্রোগোস্ট

sys.stdinএর পরিবর্তে
পিয়োটার

তবে sys.stdinএটি একটি ফাইল এবং এটি ইতিমধ্যে উন্মুক্ত এবং অবশ্যই এটি বন্ধ করা উচিত নয়। হুপের মাধ্যমে ঝাঁপ না দিয়ে ঠিক ফাইল আর্গুমেন্টের মতো হ্যান্ডেল করা অসম্ভব ।
অ্যালেক্সিস

@ অ্যালেক্সিস অবশ্যই, যদি আপনি বন্ধ করতে চান fবা প্রসঙ্গ পরিচালক ব্যবহার করতে চান তবে আপনার আরও জটিল কিছু প্রয়োজন। আমার নতুন উত্তরটি বিকল্প হিসাবে দেখুন।
মিকেল

12

কোনও ফাইলনাম আর্গুমেন্ট হিসাবে দেওয়া হয়েছে কিনা তা পরীক্ষা করুন, নাহলে পড়ুন sys.stdin

এটার মতো কিছু:

if sys.argv[1]:
   f = open(sys.argv[1])
else:
   f = sys.stdin 

এটি মাইকেলের উত্তরের মতো যা এটি sysমডিউলটি ব্যবহার না করে । আমি মনে করি যদি এটি সেখানে থাকে তবে এটি অবশ্যই কোনও কারণে থাকতে হবে ...


যদি দুটি ফাইলের নাম কমান্ড লাইনে নির্দিষ্ট করা থাকে?
মিকেল 21

3
ওহ একেবারে! আমি এটি দেখাতে বিরক্ত করি নি কারণ এটি ইতিমধ্যে আপনার উত্তরে প্রদর্শিত হয়েছিল। কোনও সময়ে আপনাকে তার কী প্রয়োজন তা সিদ্ধান্ত নেওয়ার জন্য ব্যবহারকারীকে বিশ্বাস করতে হবে। তবে আপনি যদি বিশ্বাস করেন যে এটি সর্বোত্তম edit আমার বক্তব্যটি কেবল প্রতিস্থাপনের "open(/dev/stdin")জন্য sys.stdin
রাহমু

2
if len(sys.argv)>1:পরিবর্তে আপনি চেক করতে চাইতে পারেন if sys.argv[1]:অন্যথায় আপনি পরিসীমা ত্রুটির বাইরে কোনও সূচক পান
Yibo Yang

3

আমার এটি করার পছন্দের উপায়টি পরিণত হয় ... (এবং এটি হার্বিংগারস হলো নামে একটি দুর্দান্ত ছোট্ট লিনাক্স ব্লগ থেকে নেওয়া )

#!/usr/bin/env python

import argparse, sys

parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='?')
args = parser.parse_args()
if args.filename:
    string = open(args.filename).read()
elif not sys.stdin.isatty():
    string = sys.stdin.read()
else:
    parser.print_help()

আমার সবচেয়ে ভাল লাগার কারণটি হ'ল ব্লগার যেমনটি বলেছেন, ভুলভাবে ইনপুট ছাড়াই ডাকলে এটি একটি মূর্খ বার্তা দেয়। এটি আমার বিদ্যমান পাইথন স্ক্রিপ্টগুলির এত সুন্দরভাবে স্লট করেছে যে আমি এগুলি অন্তর্ভুক্ত করার জন্য সেগুলি সমস্ত সংশোধন করেছি।


3
কখনও কখনও আপনি tty থেকে ইন্টারেক্টিভভাবে ইনপুট প্রবেশ করতে চান; চেক করা isattyএবং জামিন দেওয়া ইউনিক্স ফিল্টারগুলির দর্শনের সাথে সামঞ্জস্য নয়।
মুশিফিল

isattyওয়ার্ট ছাড়াও , এটি দরকারী এবং গুরুত্বপূর্ণ জমিটি অন্য উত্তরগুলিতে পাওয়া যায় না, সুতরাং এটি আমার উর্ধ্বে।
ট্রিপলি

3
files=sys.argv[1:]

for f in files or [sys.stdin]:
   if isinstance(f, file):
      txt = f.read()
   else:
      txt = open(f).read()

   process(txt)

/dev/stdinআমার সমস্ত সিস্টেমে অনুপলব্ধ থাকলে আমি এইভাবে এটি লিখতাম।
মাইকেল

0

আমি এই সমাধানটি ব্যবহার করছি এবং এটি একটি কবজির মতো কাজ করে। আসলে আমি একটি স্ক্রিপ্ট Calle মধ্যে ব্যবহার করছি unaccent যে একটি প্রদত্ত স্ট্রিং থেকে lowercases এবং অপসারণ কথা

argument = sys.argv[1:] if len(sys.argv) > 1 else sys.stdin.read()

আমার মনে হয় আগুনের সময়টি আমি দেখেছিলাম যে সমাধানটি এখানে ছিল ।


0

যদি আপনার সিস্টেমে না থাকে /dev/stdinবা আপনি আরও সাধারণ সমাধান চান তবে আপনি আরও জটিল কিছু চেষ্টা করতে পারেন:

class Stdin(object):
    def __getattr__(self, attr):
        return getattr(sys.stdin, attr)

    def __enter__(self):
        return self

def myopen(path):
    if path == "-":
        return Stdin()
    return open(path)

for n in sys.argv[1:] or ["-"]:
    with myopen(n) as f:
            ...

আপনি প্রস্থান করার সময় ফাইল পয়েন্টারটি সরান কেন? খারাপ ধারণা। যদি কোনও ফাইল থেকে ইনপুট পুনর্নির্দেশ করা হয়, পরবর্তী প্রোগ্রামটি এটি আবার পড়বে। (এবং যদি স্টিডিন একটি টার্মিনাল হয়, সন্ধান করুন সাধারণত কিছুই করে না, ডান?) কেবল এটিকে একা রেখে দিন।
অ্যালেক্সিস

হ্যাঁ, হয়ে গেছে। আমি কেবল -একাধিকবার ব্যবহার করা সুন্দর বলে মনে করেছি । :)
মাইকেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.