正则 想忽略前29个半角位置,但全角字符影响了。

一个文本文件中,内容如下:(注:横线上方我标记的是位置。)

123456......                30 31 32 33 ......
------------------------------------------------------------------------------------------------
AA山田 花1         1234           aaa
AA山田 下夫12       1111           aaa
AA山田 下夫1        1212           aaa
AA山田 下夫123      2323           aaa
AA山田 下夫12       8888           aaa
......
......
......

我的目的是:
  检查半角的第30位开始的连续4位不全是数字的查找出来,于是我用了这个正则:^.{29}(?!\d{4})

  但是因为第3位开始是全角的日文姓名再加一些全角的数字,而正则中的“.”匹配的是半角或全角,在匹配全角字符时,正则会当成1个字符,但实际它占了2个半角的位置,就导致“.{29}”匹配之后实际的位置就到了第32、33位之后。

  我想直接用一个正则表达式来解决这个问题,因为就是在文本文件中,不想利用编程解决。

我自己的一些思考:
  正则中是否有只匹配位置的功能?如果有的话,我就只忽略前29个半角位置,可能就能解决这个问题。

想请教朋友们,非常感谢!

不管全角还是半角,对于正则来说,都是一个字符,他不会计算这个字符到底是几位组成的

另外, 既然你已经要用正则了,就不要局限于索引位置了,局限索引位置,是字符串方法,不是正则方法

import re

a = '''AA山田 花1         1234           aaa
AA山田 下夫12       1111           aaa
AA山田 下夫1        1212           aaa
AA山田 下夫123      2323           aaa
AA山田 下夫12       8888           aaa'''

# 不能是四个数字
print(re.findall(r'(?:^|\n)([^\s]+)\s+([^\s]+)\s+((?!\d{4})[^\s]+)\s+([^\s]+)',a))

不能是四个相同数字
print(re.findall(r'(?:^|\n)([^\s]+)\s+([^\s]+)\s+((?!(\d)\4{3})[^\s]+)\s+([^\s]+)',a))


import re

a = '''
\nAA山田 花1         1234           aaa\n
\nAA山田 下夫12       1111           aaa\n
\nAA山田 下夫1        1212           aaa\n
\nAA山田 下夫123      2323           aaa\n
\nAA山田 下夫12       888a           bbbb\n

'''

# 4位非空白字符
print(re.findall(r'(?:^|\n)([\S]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)', a))

# 4位不全是数字的空白字符
print(re.findall(r'(?:^|\n)([\S]+)\s+([\S]+)\s+((?!(\d){4})[\S]+)\s+([\S]+)', a))
  1. ?: 表示一个非捕获分组,即这个分组匹配的内容不会被捕获到分组中。在正则表达式中,通常用 () 来表示一个捕获分组,用于捕获匹配的内容。但有时我们并不需要捕获匹配的内容,只是想把一些模式放在一起作为一个整体来匹配或排除一些内容,这时就可以使用非捕获分组来实现。r'(?:^|\n)' 表示一个非捕获分组。这个分组包含两个可能的匹配项:一是字符串的开头(^),二是换行符(\n)。

  2. ([\S]+)\s+
    [\S]+ 匹配1个或者一个以上的非空字符
    ([\S]+)这些非空字符被分组,需要被记住,也就是被我抓取
    \s+ 匹配1个或者1个以后上的任意空白字符

  3. ((?!(\d){4})[\S]+)
    最外层的()表示这是一个分组
    (\d){4} 表示4个数字
    (?!(\d){4}) 表示不是4个数字