格雷普和巨蟒

我需要一种使用 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不会打印

337669 次浏览
  1. use sys.argv to get the command-line parameters
  2. use open(), read() to manipulate file
  3. use the Python re module to match lines

The natural question is why not just use grep?! But assuming you can't...

import re
import sys


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


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

Things to note:

  • search instead of match to find anywhere in string
  • comma (,) after print removes carriage return (line will have one)
  • argv includes python file name, so variables need to start at 1

This doesn't handle multiple arguments (like grep does) or expand wildcards (like the Unix shell would). If you wanted this functionality you could get it using the following:

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,

Adapted from a grep in python.

Accepts a list of filenames via [2:], does no exception handling:

#!/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:] works, if you run it as an standalone executable, meaning

chmod +x

first

You might be interested in pyp. Citing my other answer:

"The Pyed Piper", or pyp, is a linux command line text manipulation tool similar to awk or sed, but which uses standard python string and list methods as well as custom functions evolved to generate fast results in an intense production environment.

Concise and memory efficient:

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


collections.deque(map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l))),maxlen=0)

It works like egrep (without too much error handling), e.g.:

cat input-file | grep.py "RE"

And here is the one-liner:

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

Note that the collections.deque function is required in Python3 because map has become a lazy function.

The real problem is that the variable line always has a value. The test for "no matches found" is whether there is a match so the code "if line == None:" should be replaced with "else:"

You can use python-textops3 :

from textops import *


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

with python-textops3 you can use unix-like commands with pipes

Not sure if your question was clear to me but to fix your code just change your if expression like the following:

import re
import sys


search_term = sys.argv[1]
f = sys.argv[2]
r = None
n = 0
with open(f, 'r') as file:
for line in file:
n=n+1
r = re.search(search_term, line)
if r:
print(f"{line} found at line {n}")
if not r:
print('no matches found')

PS: I tested it on Python 3.8.10

if you want to use grep you could

grep -E '(.*)word(.*)' file.txt || echo "pattern not found"