总流程
分析需求
对于很多人来说,正则表达式可能需要经常去搜索,我自己就经常用菜鸟教程来搜,所以就想自己写一个正则的编辑器,这样只要第一次好好搜索,之后可以用按钮来代替搜索。
代码实现
import PySimpleGUI as sg
import pyperclip
class RegularSearch:
def __init__(self):
sg.theme('LightBlue2')
self.window = None
self.window_location = (0, 0)
self.rule = {
# Todo 此处可以自行增加键值,增加后,选项会相应自动增加
'手机号': r'^1((34[0-8])|(8\d{2})|(([35][0-35-9]|4[579]|66|7[35678]|9[1389])\d{1}))\d{7}$',
'座机号': r'^(?:(?:\d{3}-)?\d{8}|^(?:\d{4}-)?\d{7,8})(?:-\d+)?$',
'统一社会信用代码': r'^(([0-9A-Za-z]{15})|([0-9A-Za-z]{18})|([0-9A-Za-z]{20}))$',
'18位身份证': r'^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$',
'银行卡号': r'^[1-9]\d{11,29}$',
'股票代码(A股)': r'^(s[hz]|S[HZ])(000[\d]{3}|002[\d]{3}|300[\d]{3}|600[\d]{3}|60[\d]{4})$',
'车牌号': r'^(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-HJ-NP-Z]{1}(?:(?:[0-9]{5}[DF])|(?:[DF](?:[A-HJ-NP-Z0-9])[0-9]{4})))|(?:[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领 A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9 挂学警港澳]{1})$',
'中文姓名': r'^(?:[\u4e00-\u9fa5·]{2,4})$',
'英文姓名': r'^[a-zA-Z][a-zA-Z\s]{0,20}[a-zA-Z]$',
'中文': r'^[\u4E00-\u9FA5]+$',
'中文和数字': r'^((?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])|(\d))+$',
}
self.columns = 2 # Todo 这个表示每行有几个按钮,比如2就是每行有2个按钮(即2列按钮)。通过调整这个数和下面的self.rule_button就可以自己增减按钮
self.rule_button = {
# Todo 此处可以自行增加键值,增加后,按钮会相应自动增加
'开头': r'^', '结尾': r'$',
'英文': r'[A-Za-z]', '汉字': r'[\u4E00-\u9FA5]',
'数字': r'\d', '英文数字': r'\w',
'空格': r'\s', '任意字符': r'.', '或': '|',
'0或1个': r'?', '0或多个': r'*', '1或多个': r'+',
'局部开始': r'\A', '局部结束': r'\Z',
'星号': r'\*', '小数点': r'\.'
}
self.rule_editor_gui()
def make_layout(self):
lay1 = sg.Col([
[sg.ML('', k='rule_multiline', size=(50, 10), font=20, focus=True, enter_submits=True)],
[sg.B('复制表达式'), sg.P(), sg.Combo(list(self.rule.keys()), default_value='常用正则', readonly=True,
enable_events=True, key='rule', size=(22, 1), visible=True)]
])
keys = list(self.rule_button.keys())
row_quality = len(keys) // self.columns # self.columns为每行的数量(即列数)
if row_quality != len(keys) / self.columns:
row_quality += 1
lay2 = []
i = j = -1
for x in list(self.rule_button.keys()):
i += 1
if i % self.columns == 0:
lay2.append([sg.B(x, k=x, size=(7, 1), visible=True)])
j += 1
else:
lay2[j].append(sg.B(x, k=x, size=(7, 1), visible=True))
lay2 = sg.Col(lay2, vertical_alignment='top')
lay = [[lay1, lay2]]
return lay
def rule_editor_gui(self):
layout = self.make_layout()
self.window = sg.Window('正则编辑器', layout, keep_on_top=True, modal=True)
while True:
event1, values1 = self.window.read()
if event1 in (None, 'Cancel'):
break
else:
self.window_location = (self.window.current_location()[0]+300, self.window.current_location()[1]+100)
if event1 == '复制表达式':
text = values1['rule_multiline']
pyperclip.copy(text)
sg.PopupOK('已复制到剪贴板', keep_on_top=True, location=self.window_location)
if event1 in self.rule_button.keys():
# Todo 这里可以根据自己需求优化逻辑
old_text = self.window['rule_multiline'].get()
if event1 == '开头':
text = self.rule_button[event1] + old_text
else:
text = old_text + self.rule_button[event1]
self.window['rule_multiline'].update(value=text)
self.window['rule_multiline'].set_focus(True)
self.window.close()
if __name__ == '__main__':
RegularSearch()
代码说明
1. self.rule
可以用来保存一些常用的正则
2. self.columns和self.rule_button
它们联合作用,可以调整每行有几个按钮,以及按钮的总数量
3. self.window_location
它是为了给弹窗提供一个坐标,这样编辑器窗口移动时,弹窗就会跟着移动,不过因为我没有考虑窗口本身的大小,所以如果窗口形状变化较大,可能弹窗的位置就会不在编辑器内。当然,这不是大问题
下步改进
1. self.rule的改进
可以使用文本文档或json文件来保存,启动界面前读取文件,将内容读成字典,赋值给self.rule。这样程序打包以后,就可以通过更改文本文档或json文件来增减选项了
2. self.columns和self.rule_button的改进
同理,也可以通过文件来存储和修改。
3.需要修改界面的情况
如果改动太大,比如按钮加的特别多,界面的形状可能会变的比较奇怪,那么还是需要修改界面代码,调整位置(比如把正则按钮放在“复制表达式”按钮的下面)