Есть ли Python эквивалентный `perl -pi -e`?

Я знаю python -c '<code>', но мне интересно, есть ли более элегантный эквивалент Python perl -pi -e '<code>'. Я до сих пор использую его для таких вещей, как поиск и замена в целом каталоге ( perl -pi -e s/foo/bar/g *или даже find . | xargs perl -pi -e s/foo/bar/gв подкаталогах).

Я на самом деле чувствую, что именно то, что делает Perl Perl (свободная форма Tim Toady-ness) - это то, что делает perl -pi -eработу так хорошо, в то время как с Python вам придется делать что-то вроде импорта модуля re, создания экземпляра re и последующего захвата STDIN, но, возможно, есть ярлык Python, который делает все это, и я пропустил (очень пропустил) ...

14.12.2008 22:57:33
Честно говоря, это звучит так, как будто бы Гвидо не одобрил бы это.
Axeman 14.12.2008 23:22:59
Конечно, вы имеете в виду найти. тип F | xargs perl ...?
Sam Kington 15.12.2008 04:07:05
Вместо этого вы можете использовать Ruby. В Ruby эквивалентом perl -pi -eявляется ruby -pi -e. Нажмите на эту ссылку для получения дополнительной информации.
unforgettableidSupportsMonica 12.12.2014 14:12:29
6 ОТВЕТОВ
РЕШЕНИЕ

Использование командной строки из ' python -h' безусловно убедительно указывает на то, что такого эквивалента нет. Perl имеет тенденцию широко использовать ' $_' (ваши примеры используют его неявно), и я не думаю, что Python поддерживает какую-либо похожую концепцию, тем самым делая Python-эквиваленты однострочными в Perl намного сложнее.

10
14.12.2008 23:53:48

Эквивалент -pi не так сложно написать на Python.

  1. Напишите себе удобный модуль с функциями -p и -i, которые вам действительно нравятся. Давайте назовем это pypi.py.

  2. использование python -c 'import pypi; pypi.subs("this","that")'

Вы можете реализовать базовый цикл -p с помощью модуля fileinput .

У вас будет функция, subsкоторая реализует необходимый алгоритм «-i» открытия файла, сохранения резервной копии и выполнения замены в каждой строке.

Есть несколько рецептов ActiveState, как это. Вот некоторые:

Не встроенный. Но не сложно написать. И однажды написано легко настроить.

10
15.12.2008 00:58:30
Я хотел бы предположить, что модуль называется pi.py, хранится в каталоге site-packages, заканчивается if __name__ == "__main__":конструкцией и затем python -mpi <arg> <arg>...
tzot 15.12.2008 09:22:10

Я думаю, что Perl лучше подходит для такого рода сценариев на лету. Если вам нужна возможность быстрого разового написания сценариев, я рекомендую придерживаться Perl, AWK, Sed и стандартных инструментов командной строки Unix.

Но если вы заинтересованы в использовании python, я использую optparse для написания собственных инструментов командной строки и рекомендую его. optparse предоставляет чистый и простой в использовании синтаксический анализатор параметров командной строки со встроенной справочной системой.

Вот пример:

def myfunc(filename, use_versbose):
   # function code

if __name__ == '__main__':
    from optparse import OptionParser

    parser = OptionParser()
    parser.add_option("-f", "--file", dest="filename",
                      help="write report to FILE", metavar="FILE")
    parser.add_option("-q", "--quiet",
                      action="store_false", dest="verbose", default=True,
                      help="don't print status messages to stdout")

    (options, args) = parser.parse_args()

    if options.filename:
        myfunc(options.filename, options.verbose)

    else:
        print 'ERROR -- Necessary command line options not given!'
        print parser.print_help()

parser.print_help () генерирует следующий вывод и автоматически отображается, когда в командной строке указывается -h или --help:

usage: <yourscript> [options]

options:
  -h, --help            show this help message and exit
  -f FILE, --file=FILE  write report to FILE
  -q, --quiet           don't print status messages to stdout
6
15.12.2008 02:45:30
Это действительно ни в коем случае не является заменой однострочника, и, следовательно, большая часть этого не является ответом на вопрос
Leon Timmermans 15.12.2008 03:01:13
Да, но, возможно, более элегантное решение - не эквивалент perl -pi -e, а написание собственных инструментов командной строки для часто выполняемых задач. «myscript.py -x this -y that» может быть чище, чем «python -c 'import this; dostuff (this, that)'». Это зависит от ваших индивидуальных потребностей и предпочтений.
monkut 15.12.2008 06:43:53

Модуль fileinput имеет возможность редактирования на месте. Вы не можете обойтись без резервных копий, хотя. Вот как это использовать для однострочника:

python -c 'import fileinput, sys; for line in fileinput.input(inplace=True): sys.stdout.write(line, "foo", "bar")'

Лично я обычно использую Perl, когда мне нужно сделать что-то подобное. Это один из немногих случаев, когда я использую Perl.

2
8.03.2012 01:05:00

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

Я думаю, что ваша команда должна быть:

pyp "p.replace('foo','bar')"
9
20.01.2013 21:51:44
Хорошая находка! pyp («Pyed Piper, Piping Python Through Pipes») от Sony Pictures Imageworks очень лаконичен, гибок, может выполнять статистику, внутренние конвейеры и т. д. Он был представлен на PYCON 2012 «Pyed Piper: современная альтернатива Python для awk, sed и другие утилиты для работы с текстом в Unix Тоби Розена "
nealmcb 29.03.2013 20:30:08
Является ли pypi.pyсохранить код? Python 3? Я посмотрел видео и архивы, которые я могу найти, датированные 2012-2015 годами - я не нашел ничего более свежего. Я упускаю очевидное (например, «его не нужно поддерживать - оно просто работает»)?
Jonathan Leffler 18.11.2019 21:31:40

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

Может быть что-то вроде:

-

import fileinput 
import sys
for line in fileinput.input("./poop", inplace=True):
    line = line.replace("foo", "bar")
    sys.stdout.write(line)

- где "./poop" можно заменить тем, где находится ваш файл, а line.replace должен поддерживать такие вещи, как line.replace ("{}". format (variablehere), "newtext")

0
15.07.2014 13:00:01