工具

编写pygrep工具, 使用python正则精确搜索

文 / sptk 来源 / 原创 阅读 / 14 17小时前

1. 编写工具的原因

linux中用于数据过滤的工 grep egrep 或者配置参数perl正则选项, 也不能用于分组精确匹配,这里我们编写一个python工具脚本来用于搜索

2. 编写pygrep.py脚本

脚本利用python中re模块来完成的, 如果想使用好 需要我们对python正则有一个很好的理解

脚本内容如下:

#!/bin/env python3
"""
用于linux命令过滤使用,基于python 正则来过滤匹配数据
"""
import os, sys, re
import argparse

parser = argparse.ArgumentParser(description='利用python正则精确匹配数据,提取命中的数据')
parser.add_argument("-l", action="store_true", help="默认跨行匹配,开启后按照行数据进行匹配")
parser.add_argument("-a", action="store_true", help="默认返回第一个命中的内容,开启后返回命中的所有内容")
parser.add_argument("-i", action="store_true", help="默认不忽略大小写, 开启后忽略大小写")
parser.add_argument("-o", action="store_true", help="默认返回正则匹配命中的行, 开启仅仅返回正则匹配的数据")
parser.add_argument("-g", "--group", type=int,  nargs='+', help="分组编号列表,至少一个数字,-g 放到最后")
parser.add_argument("re_rule", type=str, help="要匹配的字符串正则规则")
parser.add_argument("file", nargs="?", default=None, help="可选文件名,必须在最后")

args = parser.parse_args()

print(args)

#  判断文件参数是否存在, 如果存在我们匹配正则规则就从里面匹配
flags = []
#  添加正则flag
if not args.l:
    flags.append(re.DOTALL)

if args.i:
    flags.append(re.I)

# 获取数据文件对象
if args.file:
    # 如果提供文件对象, 我们匹配文件对象的内容
    f = open(args.file)
else:
    #  否则我们使用 标准输入的数据来匹配, 主要用于接收上个命令的输出数据
    f = sys.stdin

#  处理flags
flag = 0
for fg in flags[1:]:
    flag = flag | fg


def search(re_rule, data, args, flag):
    res = re.findall(args.re_rule, data, flags=flag) if args.a else re.search(args.re_rule, data, flags=flag)

    if not res:
        return

        # 判断输出命中的行还是 仅仅匹配的内容
    if not args.o:
        count = 0 if args.a else 1
        # 高亮输出匹配命中的内容
        hdata = re.sub(args.re_rule, lambda g: f"\033[1;31m{g.group()}\033[0m",data,count=count)
        print(hdata)
        return

        # 判断是否是全部匹配
    if args.a and args.o:
        for o in res:
            print(o, end=' ')
        else:
            print('')
    else:
        if not args.group:
            print(res.group(0))
        else:
            for gi in args.group:
                print(res.group(gi),end=' ')
            else:
                print('')


# 按行处理
if args.l:
    for line in f:
        # 如果查找所有, 则使用findall返回所有的, 则返回匹配到的行
        search(args.re_rule, line.strip(), args, flag)
else:
    data = f.read()
    search(args.re_rule, data, args, flag)

3. 配置脚本到linux

# 1. 方便工具我们是一个我们创建一个工具目录并将其添加到path中
mkdir -p /opt/tools
# 2. 再/opt/tools中创建我们的pygrep脚本文件 可以利用vim工具添加 也可以上传上去都可以

# 3. 给予执行权限
# 如果你是先编写py脚本 后上传的 可以对其重命名   mv /opt/tools/pygrep.py /opt/tools/pygrep
chmod a+x /opt/tools/pygrep 

# 4. 把/opt/tools添加到path环境变量
echo 'export PATH=$PATH:/opt/tools' >> /etc/profile

# 5. 刷新环境变量
source /etc/profile

# 6. 测试是否可以正常使用
pygrep --help

# 输出如下内容:
usage: pygrep [-h] [-l] [-a] [-i] [-o] [-g GROUP [GROUP ...]] re_rule [file]

利用python正则精确匹配数据,提取命中的数据

positional arguments:
  re_rule               要匹配的字符串正则规则
  file                  可选文件名,必须在最后

optional arguments:
  -h, --help            show this help message and exit
  -l                    默认跨行匹配,开启后按照行数据进行匹配
  -a                    默认返回第一个命中的内容,开启后返回命中的所有内容
  -i                    默认不忽略大小写, 开启后忽略大小写
  -o                    默认返回正则匹配命中的行, 开启仅仅返回正则匹配的数据
  -g GROUP [GROUP ...], --group GROUP [GROUP ...]
                        分组编号列表,至少一个数字,-g 放到最后

4. 测试

# 1. 匹配ls目录下面的以.conf结尾的配置文件 如果正常输出则说明可以正常使用了
ls /etc | pygrep -lo '.+\.conf$'

# 2. 利用分组做精确提取, 这样我们仅仅提取名字 不提取后缀
ls /etc | pygrep -lo '(.+)\.conf$' -g 1  

0

站点声明:站点主要用于个人技术文章。

冀ICP备19037883号
相关侵权、举报、投诉及建议等,请发E-mail:804330969@qq.com