Intereting Posts
Почему у меня нет настроек hidraw в моей системе и как я могу исправить свои устройства USB? Как получить размер специального файла блока? SED изменяет только начало строки и сохраняет конец строки Какая команда отображает все свойства моего ПК на терминале Какие разрешения я должен установить для исполняемого файла, я могу поделиться? Как можно использовать файл .iso для Debian для установки программного обеспечения без CD-диска или Интернета? RAID 5 с 4 дисками не работает с одним неисправным диском? Поиск «не новой строки» в vim? Используйте инструменты Unix для поиска блока определений в XML. zgrep против egrep против grep Как я могу разрешить приложениям связываться с любым адресом в подсети, назначенной интерфейсу? Просмотрите изменения в .tex-файлах Разделить окно tmux с той же начальной командой в новой панели tmux GNU Экранные странные символы при нажатии Кросс-компиляция и CMake

Как заставить программы python вести себя как соответствующие инструменты unix?

У меня есть несколько скриптов Python, и я работаю над их переписыванием. У меня такая же проблема со всеми из них.

Для меня не очевидно, как писать программы так, чтобы они вели себя как соответствующие инструменты unix.

Потому что это

$ cat characters | progname 

и это

 $ progname characters 

должен производить тот же результат.

Самое близкое, что я смог найти в Python, это библиотека файлов. К сожалению, я действительно не вижу, как переписать мои сценарии Python, все из которых выглядят так:

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

Библиотека fileinput обрабатывает stdin, если существует stdin, и обрабатывает файл, если есть файл. Но он выполняет итерации по одиночным линиям.

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

Я действительно этого не понимаю. Я предполагаю, что если вы имеете дело с небольшими файлами или если вы мало что делаете с файлами, это может показаться очевидным. Но для моих целей это делает его намного медленнее, чем просто открытие всего файла и чтение его в строку, как указано выше.

В настоящее время я запускаю скрипт выше, как

 $ pythonscript textfilename1 > textfilename2 

Но я хочу иметь возможность запускать его (и его братьев) в трубах, например

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

Почему не просто

 files = sys.argv[1:] if not files: files = ["/dev/stdin"] for file in files: f = open(file) ... 

Проверьте, указано ли имя файла в качестве аргумента, или прочитайте его из sys.stdin .

Что-то вроде этого:

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

Это похоже на ответ Микеля, за исключением того, что использует модуль sys . Я полагаю, что если они там, то это должно быть по какой-то причине …

Мой предпочтительный способ сделать это оказывается … (и это взято из небольшого небольшого Linux-блога под названием Harbinger's Hollow )

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

Причина, по которой мне это понравилось, заключается в том, что, как говорит блогер, она просто выводит глупое сообщение, если случайно вызвано без ввода. Он также хорошо вписывается во все мои существующие скрипты Python, которые я модифицировал для их включения.

 files=sys.argv[1:] for f in files or [sys.stdin]: if type(f) if file: txt = f.read() else: txt = open(f).read() process(txt)