Греп та Пітон


78

Мені потрібен спосіб пошуку файлу за допомогою grep за допомогою регулярного виразу з командного рядка Unix. Наприклад, коли я ввожу в командному рядку:

python pythonfile.py 'RE' 'file-to-be-searched'

Мені потрібен регулярний вираз 'RE'для пошуку у файлі та роздрукування відповідних рядків.

Ось код, який я маю:

import re
import sys

search_term = sys.argv[1]
f = sys.argv[2]

for line in open(f, 'r'):
    if re.search(search_term, line):
        print line,
        if line == None:
            print 'no matches found'

Але коли я вводжу слово, якого немає, no matches foundне друкується


1
Якщо ви дійсно хочете отримати регулярні вирази у стилі python у grep, параметр --perl-regex для grep дуже близький. Це надає підтримку регулярних виразів у стилі perl. (Крім того, моїм улюбленим варіантом grep є --color = always)
Росс Роджерс

Відповіді:


82

Закономірне питання - чому б просто не використовувати grep ?! Але припускаючи, що ви не можете ...

import re
import sys

file = open(sys.argv[2], "r")

for line in file:
     if re.search(sys.argv[1], line):
         print line,

Що слід зазначити:

  • searchзамість того matchщоб знайти де-небудь у рядку
  • кома ( ,) після printвидалення повернення каретки (рядок матиме її)
  • argv включає ім'я файлу python, тому змінні повинні починатися з 1

Це не обробляє декілька аргументів (як це робить grep) або розширює символи підстановки (як це робить оболонка Unix). Якщо ви хочете цю функцію, ви можете отримати її, використовуючи наступне:

import re
import sys
import glob

for arg in sys.argv[2:]:
    for file in glob.iglob(arg):
        for line in open(file, 'r'):
            if re.search(sys.argv[1], line):
                print line,

7
вам слід скомпілювати регулярний вираз перед використанням циклів.
ghostdog74

5
Це має два голоси проти, і я не уявляю, чому. Той, хто голосував проти, хоче залишити коментар? Я знаю, що ви можете додати компіляцію регулярних виразів тощо, але я думав, що це погіршить ясність відповіді. Я не думаю, що є щось неправильне, і я запустив код, на відміну від деяких інших відповідей
Нік Фортескю

Ця відповідь була ідеальною для мене, дякую. Ще одне коротке запитання, як би я надрукував, якщо збігів не знайдено?
Девід

6
"вам слід скомпілювати регулярний вираз перед використанням циклів.", ні, Python скомпілює та кешує його самостійно, це загальноприйнятий міф, це приємно робити з причин читабельності, хоча.
bartekbrak

4
Розумна відповідь на природне запитання: "Оскільки код є частиною набагато більшого сценарію Python, і хто в такому випадку хоче закликати grep?" Коротше кажучи, я радий, що це питання тут, оскільки я замінюю скрипт bash на сценарій Python, який, сподіваюся, простіший у системі.
Mike S

13

Стислість та ефективність пам'яті:

#!/usr/bin/env python
# file: grep.py
import re, sys

map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l)))

Він працює як egrep (без зайвої обробки помилок), наприклад:

cat input-file | grep.py "RE"

І ось однокласний:

cat input-file | python -c "import re,sys;map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l)))" "RE"

7

Адаптовано з grep у python .

Приймає список імен файлів через [2:], не обробляє винятків:

#!/usr/bin/env python
import re, sys, os

for f in filter(os.path.isfile, sys.argv[2:]):
    for line in open(f).readlines():
        if re.match(sys.argv[1], line):
            print line

sys.argv[1]resp sys.argv[2:]працює, якщо ви запускаєте його як самостійний виконуваний файл, тобто

chmod +x

спочатку


яка різниця між re.match та re.search?
OscarRyz

2
@OscarRyz див. Головну відповідь Ніка Фортескю : " searchзамість того, matchщоб знайти де-небудь у рядку"
icc97

4
  1. використовувати sys.argvдля отримання параметрів командного рядка
  2. використовувати open(), read()маніпулювати файл
  3. використовуйте модуль re Python для збігу рядків

3

Вас може зацікавити pyp . Посилаючись на іншу мою відповідь :

"Pyed Piper", або pyp, - це інструмент для обробки тексту командного рядка Linux, подібний до awk або sed, але який використовує стандартні методи рядків і списків python, а також спеціальні функції, розроблені для отримання швидких результатів в інтенсивному виробничому середовищі.


1

Ви можете використовувати python-textops3:

from textops import *

print('\n'.join(cat(f) | grep(search_term)))

з python-textops3 ви можете використовувати unix-подібні команди з каналами


0

Справжня проблема полягає в тому, що рядок змінних завжди має значення. Перевірка "не знайдено збігів" полягає в тому, чи існує збіг, тому код "if line == None:" слід замінити на "else:"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.