前端智能识别解析粘贴板内容

原理分析

说白了就是解析特定格式的文字,并将处理好的内容回填到需要的表单中。
为了程序的健壮性,我们解析时需要考虑多种情况。

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); // 获取匹配到的省code
        cityList = item?.children;
      }
    });
    cityList?.some((item: any) => {
      if (provinceText?.includes(item?.label)) {
        provinceCode.push(item?.value); // 获取匹配到的市code
        districtList = item?.children;
      }
    });
    districtList?.some((item: any) => {
      if (provinceText?.includes(item?.label)) {
        provinceCode.push(item?.value); // 获取匹配到的区code
        districtList = 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就行,其他技术栈原理类似。

不懂得留言问。加呐!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七安安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值