前端智能识别解析粘贴板内容
原理分析
说白了就是解析特定格式的文字,并将处理好的内容回填到需要的表单中。
为了程序的健壮性,我们解析时需要考虑多种情况。
1、文字行数
单行和多行的解析可以分开
单行的情况如下面这种,
姓名: 七七 电话:788 邮箱:qiqi@qiqi.com 地址:啊啊啊
多行的情况可能是
姓名: 七七
电话:788
邮箱:qiqi@qiqi.com
地址:啊啊啊
多行用:const lines = text?.split('\n');
分开解析即可
2、中英文冒号兼容
在填写地址时,用户可能打中文冒号或者英文冒号,我们需要兼容确保识别分割的时候程序不会出问题。
split(/[::]/)
即可
当然,这里也可以写正则去分割空格的情况。
3、移除文本信息前后的无用空格
用trim()
没什么好说的
4、关键信息匹配
我们需要自定义一个关键词汇库去匹配剪贴板文本信息,我们可以考虑所有关键信息放进一个词汇库,也可以根据表单字段数量分开创建多个词汇库。
列如:
1、词汇库放在一起
const keywords = ['姓名','名字','电话','电话号码','号码','手机','手机号','手机号码','邮箱','邮箱地址','邮件','地址','详细地址'
使用这种放一起的关键字的匹配,优势就是词汇库放一起比较灵活,但是后期处理文本信息的时候略微繁琐,需要拿到一段信息后把这段信息移除,否则会干扰下一段信息的获取。
2、多个词汇库
const nameKeywords = ['姓名','名字','联系人']
const phoneKeywords = ['电话','电话号码','号码','手机','手机号','手机号码']
const emailKeywords = [ '邮箱','邮箱地址','邮件']
const addressKeywords = ['地址','详细地址']
缺点是每个关键字词库只能匹配特定的字段,有多少个字段就需要多少个词汇库。
优点,可以精准匹配,大大简化操作。
实践
我们这里用多个词汇库举例,单个词汇库代码太多了,懒得写,下次想起来再更新。
1、获取粘贴板内容
无论你用的那个技术栈,总有获取粘贴板内容的方法,自己用ai搜下就行,用框架的可以搜对应框架的api,原生的就搜js获取。
2、解析
- 定义多个关键字库
const nameKeywords = ['姓名', '名字', '收件人']; // 匹配姓名关键字const phoneKeywords = ['电话', '手机号码', '手机号', '手机', '联系电话']; // 匹配号码关键字const provinceKeywords = ['所在地区', '省市区']; // 匹配省市区关键字const addressKeywords = ['详细地址', '地址', '完整地址']; // 匹配详细地址关键字
- 正则先匹配一遍关键字和值
let name = '';let phone = '';let provinceCode: string[] = [];let address = '';// 使用正则表达式匹配关键字和值const regex = new RegExp(`(${nameKeywords.join('|')})[::](.*?)(${phoneKeywords.join('|',)})[::](.*?)(${provinceKeywords.join('|')})[::](.*?)(${addressKeywords.join('|',)})[::](.*)`,'i',);const match = text.match(regex);
- 区分单行和多行处理方式
if (match) {// 动态解析关键字和值,处理一行格式的情况const parsedFields = {[match[1]]: match[2].trim(),[match[3]]: match[4].trim(),[match[5]]: match[6].trim(),[match[7]]: match[8].trim(),};name = nameKeywords.some(keyword => keyword in parsedFields)? parsedFields[nameKeywords.find(keyword => keyword in parsedFields)!]: '';phone = phoneKeywords.some(keyword => keyword in parsedFields)? parsedFields[phoneKeywords.find(keyword => keyword in parsedFields)!]: '';const provinceText = provinceKeywords.some(keyword => keyword in parsedFields)? parsedFields[provinceKeywords.find(keyword => keyword in parsedFields)!]: '';address = addressKeywords.some(keyword => keyword in parsedFields)? parsedFields[addressKeywords.find(keyword => keyword in parsedFields)!]: '';provinceCode = pareProvinceText(provinceText);}// 处理多行格式的情况else {let provinceText = '';const lines = text?.split('\n');lines.forEach(line => {const trimmedLine = line.trim();if (nameKeywords.some(keyword => trimmedLine.includes(keyword))) {name = trimmedLine.split(/[::]/).pop()?.trim() || ''; // 中英文冒号处理} else if (phoneKeywords.some(keyword => trimmedLine.includes(keyword))) {phone = trimmedLine.split(/[::]/).pop()?.trim() || '';} else if (provinceKeywords.some(keyword => trimmedLine.includes(keyword))) {provinceText = trimmedLine.split(/[::]/).pop()?.trim() || '';} else if (addressKeywords.some(keyword => trimmedLine.includes(keyword))) {address = trimmedLine.split(/[::]/).pop()?.trim() || '';}});provinceCode = pareProvinceText(provinceText);}
-
上面这里pareProvinceText这个函数是我自己的业务函数,处理省市区的,你们不用管)
-
将结果回填
let name = '';let phone = '';let provinceCode: string[] = [];let address = '';
上面的变量是我们保存的结果,回填到需要的地方就行了。
完整示例(用的react-native)
import Clipboard from '@react-native-clipboard/clipboard';// 解析省市区粘贴板const pareProvinceText = (provinceText: string) => {const provinceCode: any[] = [];let cityList: any[] = []; // 某省下所有市let districtList: any[] = []; // 某省某区下所有区let provinceName = '';areaList?.some((item: any) => {if (provinceText.includes(item?.label)) {provinceName = item?.label;provinceCode.push(item?.value); // 获取匹配到的省codecityList = item?.children;}});cityList?.some((item: any) => {if (provinceText?.includes(item?.label)) {provinceCode.push(item?.value); // 获取匹配到的市codedistrictList = item?.children;}});districtList?.some((item: any) => {if (provinceText?.includes(item?.label)) {provinceCode.push(item?.value); // 获取匹配到的区codedistrictList = item?.children;}});return provinceCode;};// 识别剪切板const onCheckClipboard = () => {Clipboard.getString().then(text => {console.log('text', text);if (!text) {return Toast.text('剪切板无内容');}const nameKeywords = ['姓名', '名字', '收件人']; // 匹配姓名关键字const phoneKeywords = ['电话', '手机号码', '手机号', '手机', '联系电话']; // 匹配号码关键字const provinceKeywords = ['所在地区', '省市区']; // 匹配省市区关键字const addressKeywords = ['详细地址', '地址', '完整地址']; // 匹配详细地址关键字let name = '';let phone = '';let provinceCode: string[] = [];let address = '';// 使用正则表达式匹配关键字和值const regex = new RegExp(`(${nameKeywords.join('|')})[::](.*?)(${phoneKeywords.join('|',)})[::](.*?)(${provinceKeywords.join('|')})[::](.*?)(${addressKeywords.join('|',)})[::](.*)`,'i',);const match = text.match(regex);if (match) {// 动态解析关键字和值,处理一行格式的情况const parsedFields = {[match[1]]: match[2].trim(),[match[3]]: match[4].trim(),[match[5]]: match[6].trim(),[match[7]]: match[8].trim(),};name = nameKeywords.some(keyword => keyword in parsedFields)? parsedFields[nameKeywords.find(keyword => keyword in parsedFields)!]: '';phone = phoneKeywords.some(keyword => keyword in parsedFields)? parsedFields[phoneKeywords.find(keyword => keyword in parsedFields)!]: '';const provinceText = provinceKeywords.some(keyword => keyword in parsedFields)? parsedFields[provinceKeywords.find(keyword => keyword in parsedFields)!]: '';address = addressKeywords.some(keyword => keyword in parsedFields)? parsedFields[addressKeywords.find(keyword => keyword in parsedFields)!]: '';provinceCode = pareProvinceText(provinceText);}// 处理多行格式的情况else {let provinceText = '';const lines = text?.split('\n');lines.forEach(line => {const trimmedLine = line.trim();if (nameKeywords.some(keyword => trimmedLine.includes(keyword))) {name = trimmedLine.split(/[::]/).pop()?.trim() || ''; // 中英文冒号处理} else if (phoneKeywords.some(keyword => trimmedLine.includes(keyword))) {phone = trimmedLine.split(/[::]/).pop()?.trim() || '';} else if (provinceKeywords.some(keyword => trimmedLine.includes(keyword))) {provinceText = trimmedLine.split(/[::]/).pop()?.trim() || '';} else if (addressKeywords.some(keyword => trimmedLine.includes(keyword))) {address = trimmedLine.split(/[::]/).pop()?.trim() || '';}});provinceCode = pareProvinceText(provinceText);}// 更新表单数据formRef.current?.setData({receiver: name,phone,addressCode: provinceCode,address,});}).catch(error => {console.log(error);});};
参考1、2就行,其他技术栈原理类似。
不懂得留言问。加呐!
相关文章:

前端智能识别解析粘贴板内容
原理分析 说白了就是解析特定格式的文字,并将处理好的内容回填到需要的表单中。 为了程序的健壮性,我们解析时需要考虑多种情况。 1、文字行数 单行和多行的解析可以分开 单行的情况如下面这种, 姓名: 七七 电话:788 邮箱&…...

AI工具发展全景分析与战略展望
AI工具发展全景分析与战略展望 本文基于本人最近整理并开发的AI工具推荐平台软件及相关的资料信息整理。 一、产业现状深度解析 (一)市场格局三维透视 #mermaid-svg-YLeCfJwoWDOd32wZ {font-family:"trebuchet ms",verdana,arial,sans-seri…...

(定时器,绘制事件,qt简单服务器的搭建)2025.2.11
作业 笔记(复习补充) 1> 制作一个闹钟软件 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> //按钮类 #include <QTimer> //定时器类 #include <QTime> //…...

C++17十大常用特性
玩转cpp小项目星球3周年了! 今天分享两个知识点: C17我常用的十大特性。git am与git apply对patch处理的不同。...

【机器学习】超参数的选择,以kNN算法为例
分类准确度 一、摘要二、超参数的概念三、调参的方法四、实验搜索超参数五、扩展搜索范围六、考虑距离权重的kNN算法七、距离的计算方法及代码实现八、明可夫斯基距离的应用九、网格搜索超参数 一、摘要 本博文讲解了机器学习中的超参数问题,以K近邻算法为例&#…...

【RabbitMQ的监听器容器Simple和Direct】 实现和场景区别
在Spring Boot中,RabbitMQ的两种监听器容器(SimpleMessageListenerContainer和DirectMessageListenerContainer)在实现机制和使用场景上有显著差异。以下是它们的核心区别、配置方式及最佳实践: Simple类型 Direct类型 一、核心…...

NO.13十六届蓝桥杯备战|条件操作符|三目操作符|逻辑操作符|!||||(C++)
条件操作符 条件操作符介绍 条件操作符也叫三⽬操作符,需要接受三个操作数的,形式如下: exp1 ? exp2 : exp3条件操作符的计算逻辑是:如果 exp1 为真, exp2 计算, exp2 计算的结果是整个表达式的结果&am…...

2025.1.8(qt图形化界面之消息框)
笔记(后期复习补充) 作业 1> 手动将登录项目实现,不要使用拖拽编程 并且,当点击登录按钮时,后台会判断账号和密码是否相等,如果相等给出登录成功的提示,并且关闭当前界面,发射一…...

旅游行业内容管理系统CMS提升网站建设效率与体验
内容概要 在如今快速发展的互联网时代,旅游行业对网站的要求越来越高,内容管理系统(CMS)的应用不可或缺。以 Baklib 为代表的先进CMS可显著提高旅游网站的建设效率与用户体验。为了满足不断变化的市场需求,这些系统通…...

使用 Scrapy 抓取网页数据
1. Scrapy 简介 Scrapy 是一个流行的 Python 爬虫框架,提供了强大的工具和灵活的扩展机制,用于高效抓取和处理网页数据。它支持异步 I/O,速度快且资源消耗低,非常适合大规模爬取任务。 2. 安装 Scrapy 确保你的 Python 环境版本…...

C# OpenCV机器视觉:SoftNMS非极大值抑制
嘿,你知道吗?阿强最近可忙啦!他正在处理一个超级棘手的问题呢,就好像在一个混乱的战场里,到处都是乱糟糟的候选框,这些候选框就像一群调皮的小精灵,有的重叠在一起,让阿强头疼不已。…...

kamailio关于via那点事
如果kamailio作为代理服务器,在转到目的路由时 不删除原始的via信息 会造成信息泄露 如果 Kamailio 作为代理服务器(SIP Proxy)在转发 SIP 请求时不删除原始的 Via 信息,这确实可能会造成信息泄露。 📌 为什么不删除 …...

[MFC] 使用控件
介绍如何使用控件,以及如何获取控件中的数值 check Box 添加点击事件,即选中和取消选中触发的事件 第一种方式是按照如下方式第二种方式是直接双击点击进去 void CMFCApplication1Dlg::OnBnClickedCheckSun() {// TODO: 在此添加控件通知处理程序代…...

【探索未来科技】2025年国际学术会议前瞻
【探索未来科技】2025年国际学术会议前瞻 【探索未来科技】2025年国际学术会议前瞻 文章目录 【探索未来科技】2025年国际学术会议前瞻前言1. 第四届电子信息工程、大数据与计算机技术国际学术会议( EIBDCT 2025)代码示例:机器学习中的线性回…...

使用wpa_supplicant和wpa_cli 扫描wifi热点及配网
一:简要说明 交叉编译wpa_supplicant工具后会有wpa_supplicant和wpa_cli两个程序生产,如果知道需要连接的wifi热点及密码的话不需要遍历及查询所有wifi热点的名字及信号强度等信息的话,使用wpa_supplicant即可,否则还需要使用wpa_…...

Sealos的k8s高可用集群搭建
Sealos 介绍](https://sealos.io/zh-Hans/docs/Intro) Sealos 是一个 Go 语言开发的简单干净且轻量的 Kubernetes 集群部署工具,能很好的支持在生产环境中部署高可用的 Kubernetes 集群。 Sealos 特性与优势 支持离线安装,工具与部署资源包分离&#…...

Android和DLT日志系统
1 Linux Android日志系统 1.1 内核logger机制 drivers/staging/android/logger.c static size_t logger_offset( struct logger_log *log, size_t n) { return n & (log->size - 1); } 写的off存在logger_log中(即内核内存buffer)&am…...

【openresty服务器】:源码编译openresty支持ssl,增加service系统服务,开机启动,自己本地签名证书,配置https访问
1,openresty 源码安装,带ssl模块 https://openresty.org/cn/download.html (1)PCRE库 PCRE库支持正则表达式。如果我们在配置文件nginx.conf中使用了正则表达式,那么在编译Nginx时就必须把PCRE库编译进Nginx…...

如何将网站提交百度收录完整SEO教程
百度收录是中文网站获取流量的重要渠道。本文以我的网站,www.mnxz.fun(当然现在没啥流量) 为例,详细讲解从提交收录到自动化维护的全流程。 一、百度收录提交方法 1. 验证网站所有权 1、登录百度搜索资源平台 2、选择「用户中心…...

【STM32】ADC|多通道ADC采集
本次实现的是ADC实现数字信号与模拟信号的转化,数字信号时不连续的,模拟信号是连续的。 1.ADC转化的原理 模拟-数字转换技术使用的是逐次逼近法,使用二分比较的方法来确定电压值 当单片机对应的参考电压为3.3v时,0~ 3.3v(模拟信…...

蓝桥杯算法日记|贪心、双指针
3412 545 2928 2128 贪心学习总结: 1、一般经常用到sort(a,an);【a[n]】排序,可以给整数排,也可以给字符串按照字典序排序 2、每次选最优 双指针 有序数组、字符串、二分查找、数字之和、反转字…...

ArcGIS Pro SDK (二十七)自定义许可
ArcGIS Pro SDK (二十七)自定义许可 环境:Visual Studio 2022 + .NET6 + ArcGIS Pro SDK 3.0 文章目录 ArcGIS Pro SDK (二十七)自定义许可1 在Config.xaml中添加扩展配置2 在Module1.cs中实现接口IExtensionConfig1 在Config.xaml中添加扩展配置 <modules><inse…...

通过客户端Chatbox或OpenwebUI访问识别不到本地ollama中的模型等问题的解决
Chatbox和Open WebUI 等无法获取到 Ollama里的模型,主要是由以下原因导致: Ollama 服务未正确暴露给 Docker 容器或客户端模型未正确下载或名称不匹配网络配置或权限问题 排查以上问题的思路首先排查ollama服务是否启动,然后再看端口号 使…...

速度超越DeepSeek!Le Chat 1100tok/s闪电回答,ChatGPT 4o和DeepSeek R1被秒杀?
2023年,当全球科技界还在ChatGPT引发的AI狂潮中沉浮时,一场来自欧洲的"静默革命"正悄然改变游戏规则。法国人工智能公司Mistral AI推出的聊天机器人Le Chat以"比ChatGPT快10倍"的惊人宣言震动业界,其背后承载的不仅是技术…...

JVM速成=。=
JVM跨平台原理 跨平台:一次编译,到处运行 本质:不同操作系统上运行的JVM不一样,只需要把java程序编译成一份字节码文件,JVM执行不同的字节码文件。 Java是高级语言,提前编译一下(变成字节码文件…...

Packer 手动修复安装腾讯云插件
文章目录 Packer [腾讯云插件文档](https://developer.hashicorp.com/packer/integrations/hashicorp/tencentcloud) 提供的版本:v1.2.0,目前 Packer 构建镜像时,不支持现有2种[硬盘类型](https://www.tencentcloud.com/zh/document/product/…...

学习总结三十
下头论文 # P10605 下头论文 题目背景 莲子一直在苦恼关于论文的灵感。她为此花了太多时间,以至于没有时间理会她的伙伴梅莉。 题目描述 一天,莲子发现了一个绝妙的点子,并希望通过实验等过程将其完善。具体来说,她需要依次完成 n…...

开发完的小程序如何分包
好几次了,终于想起来写个笔记记一下 我最开始并不会给小程序分包,然后我就各种搜,发现讲的基本上都是开发之前的小程序分包,可是我都开发完要发布了,提示我说主包太大需要分包,所以我就不会了。。。 好了…...

Flutter PIP 插件 ---- Android
在 Flutter Android 应用中实现画中画功能 画中画(Picture-in-Picture, PiP)模式允许您的应用在一个固定在屏幕角落的小窗口中运行,同时用户可以与其他应用进行交互。本指南将介绍如何在 Flutter Android 应用中实现画中画功能,包括其局限性和解决方案。 项目地址 flutter_p…...

【20250211】字符串:459.重复的子字符串
#方法一:暴力求解法 # class Solution: # def repeatedSubstringPattern(self, s): # n len(s) # substr "" # #只重复一次不算“重复多次” # if n < 1: # return False # else: # …...