Есть ли Python эквивалентный `perl -pi -e`? - PullRequest
16 голосов
/ 15 декабря 2008

Я знаю о python -c '<code>', но мне интересно, есть ли более элегантный питон, эквивалентный 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 повторный случай и затем захватить стандартный ввод, но, возможно, есть ярлык Python, который делает все это, и я пропустил это (очень пропустил это) ...

Ответы [ 7 ]

28 голосов
/ 15 декабря 2008

Python для маглов. Если вам нужна магия, Perl вам следует использовать!

10 голосов
/ 15 декабря 2008

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

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

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

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

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

Есть несколько активных рецептов, подобных этому. Вот некоторые из них:

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

10 голосов
/ 15 декабря 2008

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

9 голосов
/ 21 января 2013

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

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

pyp "p.replace('foo','bar')"
6 голосов
/ 15 декабря 2008

Я думаю, что 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
2 голосов
/ 08 марта 2012

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

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

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

0 голосов
/ 15 июля 2014

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

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

-

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»)

...