鱼C论坛

 找回密码
 立即注册
查看: 5709|回复: 19

[已解决]正则匹配问题

[复制链接]
发表于 2023-3-23 15:52:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

ctestRatio       = 30;#180/10000 = 1.8%
如上是文件中的数据,我要通过cPanelSpreadRatio在文件中搜索匹配=和;之间的30这个值,可以用r'(?<==)(?=;)匹配吗,小白不会弄,这里用=做了分隔符,但是=后面值的后面是分号,分号后面太杂乱了,所以想用=和;之间的数据作为value
部分代码如下

  1.                 def read_file(file_path):
  2.                     with open(file_path, 'rb') as f:
  3.                         # 检测文件编码
  4.                         result = chardet.detect(f.read())
  5.                         f.seek(0)
  6.                         return f.readlines()
  7.             for file_path in all_files:
  8.                 if file_path.endswith('.ini'):
  9.                     #print("打印文件:" + file_path)
  10.                     f = read_file(file_path)
  11.                     # 遍历需要抓取的key并输出对应的值
  12.                     try:
  13.                         for each_line in f:
  14.                             for key in PQ_keys:
  15.                                 if key in each_line.decode('utf-8'):
  16.                                     [color=Red]key, value = each_line.decode('utf-8').strip().split('=')[/color]
  17.                                     print('{}:{}={}'.format(file_path, key, value))
  18.                     except UnicodeDecodeError:
  19.                         print('解码文件 {} 时发生错误'.format(file_path))  
复制代码
最佳答案
2023-3-23 20:17:35
liyuping-fisher 发表于 2023-3-23 20:14
lst = re.findall(fr"\s*=\s*(\S+?;)", each_line.decode('utf-8'))
                                 ...

[b]因为我用了一个 f-string 的语法是 python 3.6 以后才有的,你可以改一下

            for file_path in all_files:
                if file_path.endswith('.ini'):
                    #print("打印文件:" + file_path)
                    f = read_file(file_path)
                    # 遍历需要抓取的key并输出对应的值
                    try:
                        for each_line in f:
                            for key in PQ_keys:
                                text = each_line.decode('utf-8')
                                if key in text:
                                    lst = re.findall(r"{}\s*=\s*(\S+?);".format(key), text)
                                    print(key)#这里打印出来的是key列表没问题
                                    print(lst)#这里打印出来是空,没匹配到?
                                    if lst:
                                        for value in lst:
                                            print('{}:{}={}'.format(file_path, key, value))

                    except UnicodeDecodeError:
                        print('解码文件 {} 时发生错误'.format(file_path))
[/b]
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-3-23 15:59:41 | 显示全部楼层
本帖最后由 isdkz 于 2023-3-23 16:05 编辑

正则表达式可以用 ctestRatio\s*=\s*(\S+);

示例代码:

  1. import re

  2. pattern= re.compile(r"ctestRatio\s*=\s*(\S+);")
  3. s = "ctestRatio       = 30;#180/10000 = 1.8%"
  4. lst = pattern.findall(s)
  5. print(lst)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 16:33:04 | 显示全部楼层
可以尝试一下这上代码:
  1. import re

  2. ctestRatio = 30
  3. pattern = r'=(\d+);'
  4. for each_line in f:
  5.     for key in PQ_keys:
  6.         if key in each_line.decode('utf-8'):
  7.             match = re.search(pattern, each_line.decode('utf-8'))
  8.             if match:
  9.                 value = int(match.group(1))
  10.                 if value == ctestRatio:
  11.                     print('{}:{}={}'.format(file_path, key, value))
复制代码

首先定义了一个变量ctestRatio,它存储了我们要查找的值。然后,使用了re.search()函数来搜索每一行中匹配正则表达式r'=(\d+);'的内容。这个正则表达式表示,我们要查找一个以=开头、以;结尾的子字符串,并将其中的数字捕获到一个分组中。如果找到了这样的子字符串,将其捕获的数字转换成整数,并与ctestRatio比较。如果相等,则打印文件路径、键和值。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 16:51:52 | 显示全部楼层
isdkz 发表于 2023-3-23 15:59
正则表达式可以用 ctestRatio\s*=\s*(\S+);

示例代码:

没太明白,ctestRatio这个是个变量,也就是代码中的key,因为我有很多key
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 16:54:12 | 显示全部楼层
ouyunfu 发表于 2023-3-23 16:33
可以尝试一下这上代码:
首先定义了一个变量ctestRatio,它存储了我们要查找的值。然后,使用了re.search( ...

代码中的key本身是个变量,这个变量的值是“ctestRataio”,也可能是其实,我是通过这个key的变量在文件中找到"ctestRatio       = 30;#180/10000 = 1.8%"这一行(只是一个key搜索出来的结果),在取其=和;之间的数据
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 16:54:17 | 显示全部楼层
liyuping-fisher 发表于 2023-3-23 16:51
没太明白,ctestRatio这个是个变量,也就是代码中的key,因为我有很多key

也就是你要匹配每一个等号和分号之间的内容作为 value,前面的内容作为 key?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 16:55:45 | 显示全部楼层
isdkz 发表于 2023-3-23 16:54
也就是你要匹配每一个等号和分号之间的内容作为 value,前面的内容作为 key?

是的是的,用key这个变量遍历每一行,然后每一行的数据大概就是“"ctestRatio       = 30;#180/10000 = 1.8%"这样的,我要等号前面的就是key,=和;之间的是我要提起的value
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 17:03:06 | 显示全部楼层
liyuping-fisher 发表于 2023-3-23 16:55
是的是的,用key这个变量遍历每一行,然后每一行的数据大概就是“"ctestRatio       = 30;#180/10000 = 1 ...

看看这是不是你想要的效果

参考代码:
  1. import re

  2. pattern= re.compile(r"(\S+)\s*=\s*(\S+);")
  3. s = """ctestRatio       = 30;#180/10000 = 1.8%
  4. a       = 31;#180/10000 = 1.8%
  5. b       = 32;#180/10000 = 1.8%
  6. c       = 33;#180/10000 = 1.8%
  7. #180/10000 = 1.8%
  8. #180/10000 = 1.8%
  9. #180/10000 = 1.8%
  10. d       = 33;#180/10000 = 1.8%"""
  11. f = s.splitlines()
  12. file_path = "test.txt"

  13. for each_line in f:
  14.     lst = pattern.findall(each_line)
  15.     if lst:
  16.         for i in lst:
  17.             key, value = i
  18.             print('{}:{}={}'.format(file_path, key, value))
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 17:21:27 | 显示全部楼层
isdkz 发表于 2023-3-23 17:03
看看这是不是你想要的效果

参考代码:

这个方法lst打印出来是空的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 17:23:57 | 显示全部楼层
isdkz 发表于 2023-3-23 17:03
看看这是不是你想要的效果

参考代码:
  1.             for file_path in all_files:
  2.                 if file_path.endswith('.ini'):
  3.                     #print("打印文件:" + file_path)
  4.                     f = read_file(file_path)
  5.                     # 遍历需要抓取的key并输出对应的值
  6.                     try:
  7.                         for each_line in f:
  8.                             for key in PQ_keys:
  9.                                 if key in each_line.decode('utf-8'):
  10.                                     pattern = re.compile(r"(\S+)\s*=\s*(\S+);")
  11.                                     lst = pattern.findall(key)
  12.                                     print(key)#这里打印出来的是key列表没问题
  13.                                     print(lst)#这里打印出来是空,没匹配到?
  14.                                     if lst:
  15.                                         for i in lst:
  16.                                             print(i)
  17.                                             key,value = i
  18.                                             print('{}:{}={}'.format(file_path, key, value))
  19.                     except UnicodeDecodeError:
  20.                         print('解码文件 {} 时发生错误'.format(file_path))
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 17:24:58 | 显示全部楼层
liyuping-fisher 发表于 2023-3-23 17:21
这个方法lst打印出来是空的

你先看看我那个参考代码中的 s 是不是像你文件中的格式,然后执行看看是不是你想要的效果

然后再相对应地改
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 17:28:45 | 显示全部楼层

            for file_path in all_files:
                if file_path.endswith('.ini'):
                    #print("打印文件:" + file_path)
                    f = read_file(file_path)
                    # 遍历需要抓取的key并输出对应的值
                    try:
                        pattern = re.compile(r"(\S+)\s*=\s*(\S+);")            # 这个可以放到外边,预编译是为了提升效率的,不用每次循环都编译一遍
                        for each_line in f:
                            for key in PQ_keys:
                                if key in each_line.decode('utf-8'):
                                    
                                    lst = pattern.findall(each_line)                    # 这里不应该是在 each_line 每一行的内容中查找吗,你那里用了 key
                                    print(key)#这里打印出来的是key列表没问题
                                    print(lst)#这里打印出来是空,没匹配到?
                                    if lst:
                                        for i in lst:
                                            print(i)
                                            key,value = i
                                            print('{}:{}={}'.format(file_path, key, value))
                    except UnicodeDecodeError:
                        print('解码文件 {} 时发生错误'.format(file_path))
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 17:35:41 | 显示全部楼层
isdkz 发表于 2023-3-23 17:28
for file_path in all_files:
                if file_path.endswith('.ini'):
          ...

解释下为啥是key
我这边key的变量是从这个列表拿的
PQ_keys = ['m_pPanelName', 'm_bPanelDualPort', 'cPanelSpreadRatio']

然后这里的each_line是文件里面的如下内容一行行的,就是通过key(m_pPanelName)去找下面文件里面的行,再获取定位到行的=和;之间的数据
cRGainYpbpr2   = "0xed730"; #fdrfe  trest
cGGainYpbpr2   = "0xea93d";
cBGainYpbpr2   = "0xee6fc";                        #fdrfe  tresttete
m_pPanelName = "0";
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 17:43:44 | 显示全部楼层
liyuping-fisher 发表于 2023-3-23 17:35
解释下为啥是key
我这边key的变量是从这个列表拿的
PQ_keys = ['m_pPanelName', 'm_bPanelDualPort', ' ...


            for file_path in all_files:
                if file_path.endswith('.ini'):
                    #print("打印文件:" + file_path)
                    f = read_file(file_path)
                    # 遍历需要抓取的key并输出对应的值
                    try:
                        pattern = re.compile(r"(\S+)\s*=\s*(\S+);")            # 这个可以放到外边,预编译是为了提升效率的,不用每次循环都编译一遍
                        for each_line in f:
                            # for key in PQ_keys:                               这个不要
                                # if key in each_line.decode('utf-8'):                       这个不要
                                    text = each_line.decode('utf-8')
                                    lst = pattern.findall(text)                    

                                    print(key)#这里打印出来的是key列表没问题
                                    print(lst)#这里打印出来是空,没匹配到?
                                    if lst:
                                        for i in lst:
                                            key, value = i
                                            if key in PQ_keys:
                                                print('{}:{}={}'.format(file_path, key, value))

                    except UnicodeDecodeError:
                        print('解码文件 {} 时发生错误'.format(file_path))
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 17:49:20 | 显示全部楼层
isdkz 发表于 2023-3-23 17:43
for file_path in all_files:
                if file_path.endswith('.ini'):
        ...

注释的那两行不能不要,因为文件里面很多行,而我搜的只是PQ_keys列表里面的几个,这个key是PQ_keys里面的元素,我要先确认这个key在PQ_keys里面,再通过这个key值去文件里面找到有key值的这一行
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 17:53:04 | 显示全部楼层
liyuping-fisher 发表于 2023-3-23 17:49
注释的那两行不能不要,因为文件里面很多行,而我搜的只是PQ_keys列表里面的几个,这个key是PQ_keys里面 ...

你先去掉看看效果
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 17:56:34 | 显示全部楼层
isdkz 发表于 2023-3-23 17:53
你先去掉看看效果

我看了的,去掉它是把文件里面的每一行处理了得到类似如下的数据
xx路径/xx文件.ini:cRGainYpbpr2="0xed730",数据太多了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 18:11:02 | 显示全部楼层
liyuping-fisher 发表于 2023-3-23 17:56
我看了的,去掉它是把文件里面的每一行处理了得到类似如下的数据
xx路径/xx文件.ini:cRGainYpbpr2="0xed ...

            for file_path in all_files:
                if file_path.endswith('.ini'):
                    #print("打印文件:" + file_path)
                    f = read_file(file_path)
                    # 遍历需要抓取的key并输出对应的值
                    try:
                        for each_line in f:
                            for key in PQ_keys:
                                text = each_line.decode('utf-8')
                                if key in text:
                                    lst = re.findall(rf"{key}\s*=\s*(\S+?);", text)
                                    print(key)#这里打印出来的是key列表没问题
                                    print(lst)#这里打印出来是空,没匹配到?
                                    if lst:
                                        for value in lst:
                                            print('{}:{}={}'.format(file_path, key, value))

                    except UnicodeDecodeError:
                        print('解码文件 {} 时发生错误'.format(file_path))
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-3-23 20:14:23 | 显示全部楼层
isdkz 发表于 2023-3-23 18:11
for file_path in all_files:
                if file_path.endswith('.ini'):
          ...

lst = re.findall(fr"\s*=\s*(\S+?;)", each_line.decode('utf-8'))
                                               ^

这里有个语法错误,我打死也没找到语法错误,用的python版本是3.4,指向的好像是双引号~
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-23 20:17:35 | 显示全部楼层    本楼为最佳答案   
liyuping-fisher 发表于 2023-3-23 20:14
lst = re.findall(fr"\s*=\s*(\S+?;)", each_line.decode('utf-8'))
                                 ...

[b]因为我用了一个 f-string 的语法是 python 3.6 以后才有的,你可以改一下

            for file_path in all_files:
                if file_path.endswith('.ini'):
                    #print("打印文件:" + file_path)
                    f = read_file(file_path)
                    # 遍历需要抓取的key并输出对应的值
                    try:
                        for each_line in f:
                            for key in PQ_keys:
                                text = each_line.decode('utf-8')
                                if key in text:
                                    lst = re.findall(r"{}\s*=\s*(\S+?);".format(key), text)
                                    print(key)#这里打印出来的是key列表没问题
                                    print(lst)#这里打印出来是空,没匹配到?
                                    if lst:
                                        for value in lst:
                                            print('{}:{}={}'.format(file_path, key, value))

                    except UnicodeDecodeError:
                        print('解码文件 {} 时发生错误'.format(file_path))
[/b]
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-10 05:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表