Как реализовать общие идиомы Bash в Python? [закрыто]


242

В настоящее время я выполняю свои манипуляции с текстовым файлом через кучу плохо запомнившихся AWK, sed, Bash и чуть-чуть Perl.

Я видел упомянутое несколько мест, где Python хорош для такого рода вещей. Как я могу использовать Python для замены сценариев оболочки, AWK, sed и друзей?


3
pythonpy - хороший конкурент для awk и sed, использующих синтаксис python: github.com/Russell91/pythonpy
RussellStewart

4
Вы можете использовать shellpy, который был разработан с идеей замены bash / sh на python github.com/lamerman/shellpy
Александр Пономарев

Это мой вопрос, я не понимаю, почему это основано на мнении. В верхнем ответе перечислены все основные действия, которые выполняет оболочка, и рассказывается, как это сделать в python. Это, на мой взгляд, отвечает на вопрос без мнения.
Крис Джефферсон

Этот вопрос и его закрытие обсуждаются здесь
Эрик,

Ответы:


144

Любая оболочка имеет несколько наборов функций.

  • Основные команды Linux / Unix. Все это доступно через библиотеку подпроцесса . Это не всегда лучший выбор для выполнения всех внешних команд. Посмотрите также на shutil для некоторых команд, которые являются отдельными командами Linux, но вы, вероятно, могли бы реализовать их непосредственно в своих скриптах Python. Другая огромная партия команд Linux находится в библиотеке os ; Вы можете сделать это проще в Python.

    И - бонус! -- быстрее. Каждая отдельная команда Linux в оболочке (за некоторыми исключениями) разветвляется на подпроцесс. Используя Python shutilи osмодули, вы не разветвляетесь на подпроцесс.

  • Особенности среды оболочки. Это включает в себя материал, который устанавливает командную среду (текущий каталог и переменные среды и что-нет). Вы можете легко управлять этим напрямую из Python.

  • Особенности программирования оболочки. Это вся проверка кода состояния процесса, различные логические команды (если, while, for и т. Д.), Команда test и все ее родственники. Определение функций вещи. Это все намного проще в Python. Это одна из огромных побед в избавлении от bash и в Python.

  • Особенности взаимодействия. Это включает в себя историю команд и что-нет. Вам не нужно это для написания сценариев оболочки. Это только для человеческого взаимодействия, а не для написания сценариев.

  • Функции управления файлами оболочки. Это включает в себя перенаправление и конвейеры. Это сложнее. Многое из этого можно сделать с помощью подпроцесса. Но некоторые вещи, которые легко в оболочке, неприятны в Python. Конкретно такие вещи, как (a | b; c ) | something >result. Это запускает два процесса параллельно (с выводом в aкачестве входных данных b), а затем третий процесс. Вывод из этой последовательности выполняется параллельно, somethingи вывод собирается в файл с именем result. Это просто сложно выразить на любом другом языке.

Определенные программы (awk, sed, grep и т. Д.) Часто могут быть переписаны как модули Python. Не уходи за борт. Замените то, что вам нужно, и развивайте свой модуль "grep". Не начинайте писать модуль Python, который заменяет «grep».

Лучше всего, что вы можете сделать это поэтапно.

  1. Замените AWK и PERL на Python. Оставь все остальное в покое.
  2. Посмотрите на замену GREP на Python. Это может быть немного сложнее, но ваша версия GREP может быть адаптирована к вашим потребностям в обработке.
  3. Посмотрите на замену FIND на петли Python, которые используют os.walk. Это большая победа, потому что вы не создаете столько процессов.
  4. Посмотрите, как заменить обычную логику оболочки (циклы, решения и т. Д.) Скриптами Python.

6
писал: "Особенности взаимодействия. Это включает в себя историю команд и что-нет. Вам это не нужно". Боюсь, никто не может сказать, что человеку действительно нужно или нет. Возможно, он делает. Кроме того, эти средства имеют большой смысл в интерактивной оболочке, взяв в качестве примера разницу между Idle и IPython.
Хелтонбайкер

47
Я искренне желаю, чтобы люди вообще отказались от сценариев оболочки. Я понимаю, что хакерство - это практически религия в мире * nix, но я очень устал от попыток интерпретировать все хакерские обходные пути, внедренные в ОС. Новизна микроинструментов (awk, sed, top, base и т. Д.) Сошла на нет в тот день, когда все решили выпустить свою собственную версию. Я смущаюсь, когда представляю, сколько человеко-часов потрачено впустую на дрянные инструменты, которые можно легко заменить парой хорошо спроектированных модулей Python. :: вздох ::
Эван Плейс

40
Я не согласен с @EvanPlaice, потому что Python-версия нескольких findскриптов, которые у меня есть, уродлива и длинна и не поддерживается в сравнении. Многие вещи должны быть сценариями оболочки, многие другие не должны . Не все должно быть только одним из Python или BASH (или что-то еще).
Майкбабкок

8
@mikebabcock В идеале должна быть полная библиотека, в которой реализованы все микроинструменты, доступные в базовом стеке * nix. Такие функции, как find () и last (), будут включены, и вместо каналов комбинация карри и отложенной загрузки будет обрабатывать их все вместе. Разве не было бы неплохо иметь среду сценариев POSIX, которая работает стандартным образом во всех дистрибутивах? Ничего подобного не существует, пока ...
Эван Плейс

2
Вопрос о конвейерах оболочки (таких как (a | b; c ) | something >result) несколько смягчен тем, что тривиально упрощается передача оболочек в subprocessметоды, использующиеshell=True
iruvar

103

Ну конечно; естественно :)

Взгляните на эти библиотеки, которые помогут вам больше никогда не писать сценарии оболочки (девиз Plumbum).

Кроме того, если вы хотите заменить awk, sed и grep чем-то, основанным на Python, я рекомендую pyp -

«Pyed Piper», или pyp, представляет собой инструмент для работы с текстом командной строки linux, похожий на awk или sed, но в котором используются стандартные методы строк и списков python, а также пользовательские функции, разработанные для быстрого получения результатов в интенсивной производственной среде.


Также взгляните на Envoy, который является альтернативой sh github.com/kennethreitz/envoy
AllanLRH

57

Я только что обнаружил, как сочетать лучшие части bash и ipython. До сих пор это кажется мне более удобным, чем использование подпроцесса и так далее. Вы можете легко скопировать большие части существующих сценариев bash и, например, добавить обработку ошибок способом Python :) И вот мой результат:

#!/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 docs о командах системной оболочки и использовании его в качестве системной оболочки .


11
Проголосовал, потому что по какой-то странной причине никто больше не упомянул! -Команды в IPython, которые являются абсолютно ключевыми; тем более что вы также можете назначить их вывод переменной (список строк), как вfilelines = ! cat myfile
kampu

И вы можете использовать переменные Python, как $varв команде оболочки? Вот это да. Это должен быть принятый ответ.
Чиль тен Бринке

И вы также можете использовать его из тетрадей Jupyter
Юваль Ацмон

44

Начиная с 2015 года и выпуска Python 3.4, теперь имеется достаточно полная интерактивная пользовательская оболочка, доступная по адресу: http://xon.sh/ или https://github.com/scopatz/xonsh.

В демонстрационном видео не показаны используемые каналы, но они поддерживаются в режиме оболочки по умолчанию.

Xonsh ('раковина') очень старается подражать bash, поэтому вещи, для которых вы уже приобрели мышечную память, например

env | uniq | sort -r | grep PATH

или

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

все равно будет работать нормально.

Учебное пособие довольно длинное и, по-видимому, охватывает значительную часть функциональности, которую обычно ожидают при появлении команды ash или bash:

  • Компилирует, оценивает и выполняет!
  • История команд и завершение табуляции
  • Помочь и помочь с ? &??
  • Псевдонимы и индивидуальные приглашения
  • Выполняет команды и / или *.xsh сценарии, которые также могут быть импортированы
  • Переменные среды, включая поиск с ${}
  • Перенаправление ввода / вывода и объединение
  • Фоновые задания и управление заданиями
  • Вложенные подпроцессы, трубы и сопроцессы
  • Режим подпроцесса, когда команда существует, иначе режим Python
  • Захваченный подпроцесс с $(), Неподхваченный подпроцесс с $[], Оценка Python с@()
  • Глобализация имени файла с помощью *или регулярное выражение

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

Кажется, у него есть некоторые недостатки, такие как требование использовать .xshрасширение для файлов с кодом xonsh: github.com/xonsh/xonsh/issues/2478 . В противном случае вы должны использовать evalxдля вызова его непосредственно из .pyфайлов.
Андри

31
  • Если вы хотите использовать Python в качестве оболочки, почему бы не взглянуть на IPython ? Также хорошо изучать язык в интерактивном режиме.
  • Если вы много работаете с текстом, и если вы используете Vim в качестве текстового редактора, вы также можете напрямую писать плагины для Vim в python. просто наберите ": help python" в Vim и следуйте инструкциям или посмотрите эту презентацию . Написание функций настолько просто и эффективно, что вы будете использовать их прямо в редакторе!

8
есть профиль ipython под названием 'sh', который делает интерпретатор очень похожим на оболочку.
Автоплектика

3
Профиль ipython 'sh' уже давно удален.
gdw2

>>> результат =! dmesg | grep -i 'usb' # the! оператор делает все это
Permafacture

16

В начале были sh, sed и awk (и найти, и grep, и ...). Это было хорошо. Но awk может быть странным маленьким зверем, и его трудно запомнить, если вы не используете его часто. Тогда великий верблюд создал Perl. Perl был мечтой системного администратора. Это было похоже на скриптинг на стероидах. Обработка текста, включая регулярные выражения, была лишь частью языка. Тогда это стало ужасно ... Люди пытались создавать большие приложения с помощью Perl. Не поймите меня неправильно, Perl может быть приложением, но оно может (может!) Выглядеть беспорядком, если вы не очень осторожны. Тогда есть весь этот плоский бизнес данных. Этого достаточно, чтобы свести программиста с ума.

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

Теперь, большая часть негатива по отношению к Perl - это вопрос мнения, и, конечно, некоторые люди могут писать очень чистый Perl, но из-за того, что многие люди жалуются на то, что слишком легко создавать запутанный код, вы знаете, что здесь есть доля правды. Тогда возникает вопрос: будете ли вы когда-нибудь использовать этот язык для более чем простой замены скриптов bash? Если нет, изучите еще немного Perl .. это просто фантастика. С другой стороны, если вам нужен язык, который будет расти вместе с вами, если вы хотите делать больше, я могу предложить Python или Ruby.

В любом случае, удачи!


9

Я предлагаю удивительную книгу онлайн Dive Into Python . Это то, как я выучил язык изначально.

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


1
... основной вопрос ответов только для ссылок.
Жан-Франсуа Фабр


7

Одна из причин, по которой я люблю Python, заключается в том, что он гораздо лучше стандартизирован, чем инструменты POSIX. Я должен дважды и трижды проверить, что каждый бит совместим с другими операционными системами. Программа, написанная в системе Linux, может не работать так же в системе BSD OSX. С Python я просто должен проверить, что целевая система имеет достаточно современную версию Python.

Более того, программа, написанная на стандартном Python, будет работать даже на Windows!


1
«Программа, написанная на стандартном Python, будет работать даже на Windows»: не шучу?
Жан-Франсуа Фабр

6

Я выскажу свое мнение на основе опыта:

Для оболочки:

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

Для питона:

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

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


4

pythonpy - это инструмент, который обеспечивает легкий доступ ко многим функциям из awk и sed, но с использованием синтаксиса python:

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

3

Я создал полудлинные сценарии оболочки (300-500 строк) и код Python, который выполняет аналогичные функции. Когда выполняется много внешних команд, я считаю, что оболочка проще в использовании. Perl также является хорошим вариантом, когда много текстовых манипуляций.


3

Исследуя эту тему, я нашел этот проверочный код (с помощью комментария на 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)

2

Ваша лучшая ставка - это инструмент, специально предназначенный для вашей проблемы. Если он обрабатывает текстовые файлы, то Sed, Awk и Perl являются главными претендентами. Python - это динамическая система общего назначения. язык . Как и с любым языком общего назначения, есть поддержка манипулирования файлами, но это не основная цель. Я бы рассмотрел Python или Ruby, если бы у меня были требования к динамическому языку, в частности.

Короче, выучите Sed и Awk очень хорошо, а также все другие вкусности, которые идут с вашим вкусом * nix (все встроенные функции Bash, grep, tr и так далее). Если вас интересует обработка текстовых файлов, вы уже используете правильные вещи.


2

Вы можете использовать python вместо bash с библиотекой 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')

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

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

Эта строка сначала выполняется git log --pretty=oneline --grep='Create'в оболочке, а затем присваивает результат переменной log. Результат имеет следующие свойства:

stdout весь текст из stdout выполненного процесса

stderr весь текст из stderr выполненного процесса

код возврата код выполнения

Это общий обзор библиотеки, более подробное описание с примерами можно найти здесь .


1

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

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

Очень простой пример, чтобы почувствовать.

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, они вам понадобятся первыми.


1

Я опубликовал пакет на PyPI: ez .
Используйте pip install ezдля его установки.

Он упаковал общие команды в оболочке, и моя библиотека использует в основном тот же синтаксис, что и оболочка. например, cp (источник, место назначения) может обрабатывать как файлы, так и папки! (обертка shutil.copy shutil.copytree и она решает, когда использовать какую). Еще приятнее то, что он может поддерживать векторизацию как R!

Другой пример: нет os.walk, используйте fls (path, regex) для рекурсивного поиска файлов и фильтрации с регулярным выражением, и он возвращает список файлов с полным или без полного пути

Последний пример: вы можете комбинировать их для написания очень простых скриптов:
files = fls('.','py$'); cp(files, myDir)

Определенно проверьте это! Это стоило мне сотни часов, чтобы написать / улучшить это!


1
Выглядит интересно, но я не могу пробиться через неформатированные документы на pypi.python.org/pypi/ez , извините ...
Грег Дубицки
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.