`
ztianyi312
  • 浏览: 18266 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

表达式中中文替换的问题(一)

阅读更多
在EAS HR模块的薪酬部分,用户可以自定义薪酬的公式,公式中变量名就是薪酬项目的名称,在运算中应该将其转换为响应的编码。一般以为直接使用字符串替换的方法就可以了,但是会遇到如下问题:
公式“ 薪酬总额  = 项目工资+绩效工资(其他)+绩效工资”
经过替换后可能会变成“f1=f2+f3(其他)+f3”,即当薪酬项目名称中包含其他薪酬项目名称的时候可能会出现错误的替换,这个问题其实用一个简单的办法就可以避免,先替换名称较长的薪酬项目再替换名称较短的薪酬项目就可以了,但是有没有更好的办法呢?
      用正则表达式可以解决这个问题。

      以下就是我的第一个实现:
public class ExpressionRegex {

 private final static String operators = "+-*/()&|=! ";//运算符
 
 public static String replace(String express,Map<String,String> replaceMap)
 {
  Iterator iter = replaceMap.entrySet().iterator();
  StringBuilder sb = new StringBuilder();
  String tail = "";
  
  while(iter.hasNext())
  {
   Map.Entry<String,String> entry = (Map.Entry<String,String>)iter.next();
   String key = entry.getKey();
   String value = entry.getValue();
   
   sb.append(tail);
   sb.append(operators);
    tail = "|";
  }
  
  Pattern p = Pattern.compile(sb.toString());
  Matcher m = p.matcher(express);
  StringBuffer result = new StringBuffer();
  while (m.find()) {
   String reg = m.group();
   int start = m.start();
   int end = m.end();
   
   if(start != 0 && operators.indexOf(express.substring(start-1, start)) == -1)
   {
    continue;
   }
   
   if(end != express.length() && operators.indexOf(express.substring(end, end+1)) == -1)
   {
    continue;
   }
   
   
      m.appendReplacement(result, replaceMap.get(reg));
  }
  m.appendTail(result);
  
  return result.toString();
 }
} 





该方法检查匹配项的前后各一个字符看他们是不是运算符或者开始结尾,通过这种办法来检查该匹配项是不是一个完整的项目名称而不是名称的一部分。为了只进行一次匹配循环,我把全部的项目名称合在了一起,但是这样又会有另外一个问题,
“绩效工资(其他)”在匹配完“绩效工资”之后不会再匹配“绩效工资(其他)”,于是又想到运用正则表达式分组,让匹配项的前后必须为运算符或者为开始或者结尾,表达式为“([+\\-*/()&|=! ]+|^)”。但是这个方法也是有问题的,符号匹配前一项后不会再匹配下一项。
暂时没想到其他的方法,先就这样吧。

可行代码:

public class ExpressionRegex {

 private String operators = null;

 public ExpressionRegex() {
  this.operators = "+\\-*/()&|=! ";
 }

 public ExpressionRegex(String regex) {
  this.operators = regex;
 }

 public String replace(String express, Map<String, String> replaceMap) {
  Iterator iter = replaceMap.entrySet().iterator();

  while (iter.hasNext()) {
   Map.Entry<String, String> entry = (Map.Entry<String, String>) iter
     .next();
   String key = entry.getKey();
   String value = entry.getValue();
   StringBuilder sb = new StringBuilder();
   sb.append("([");
   sb.append(operators);
   sb.append("]+|^)(");
   sb.append(key);
   sb.append(")([");
   sb.append(operators);
   sb.append("]+|$)");

   Pattern p = Pattern.compile(sb.toString());
   Matcher m = p.matcher(express);
   StringBuffer result = new StringBuffer();
   while (m.find()) {
    int index = 2;
    // int groupCount = m.groupCount();
    // while(m.group(index) == null && index < groupCount)index+=3;
    String reg = m.group(index);
    m.appendReplacement(result, m.group(index - 1)
      + replaceMap.get(reg) + m.group(index + 1));
   }
   m.appendTail(result);
   express = result.toString();
  }
  return express;
 }
 

这个问题之前一直没很好的解决,今天总算圆满了主要是通过正则表达式中的\G解决的,之前不太懂这个\G的意思,所以一直没用

       其实这儿问题还有其他的很多办法:
       1.写个算法替换边界运算符中间的文字
       2.给中文字符用字母进行编码,中文变量就那么几个

       不过正则表达式的办法还是最好的,通过这个办法还可以解决其他的很多问题,这里列出全部,以及测试代码:

//ExpressionRegex.java

package com.ztianyi.regex;

import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author tianji_zhou
 *
 * <p>表达式中文替换
 */
public class ExpressionRegex {

 private String operators = null;

 public ExpressionRegex() {
  this.operators = "+\\-*/()&|=! ";
 }

 public ExpressionRegex(String regex) {
  this.operators = regex;
 }

 /**
  * 
  * @param express
  * @param replaceMap
  * @return
  * 
  * 一次只能匹配一个词,需要循环多次
  */
 public String replace(String express, Map<String, String> replaceMap) {
  Iterator iter = replaceMap.entrySet().iterator();

  while (iter.hasNext()) {
   Map.Entry<String, String> entry = (Map.Entry<String, String>) iter.next();
   String key = entry.getKey();
   String value = entry.getValue();
   StringBuilder sb = new StringBuilder();
   sb.append("([");
   sb.append(operators);
   sb.append("]+|^)(");
   sb.append(key);
   sb.append(")([");
   sb.append(operators);
   sb.append("]+|$)");

   Pattern p = Pattern.compile(sb.toString());
   Matcher m = p.matcher(express);
   StringBuffer result = new StringBuffer();
   while (m.find()) {
    int index = 2;
    // int groupCount = m.groupCount();
    // while(m.group(index) == null && index < groupCount)index+=3;
    String reg = m.group(index);
    m.appendReplacement(result, m.group(index - 1)
      + replaceMap.get(reg) + m.group(index + 1));
   }
   m.appendTail(result);
   express = result.toString();
  }
  return express;
 }

 /**
  * 
  * @param express
  * @param replaceMap
  * @return
  * 
  * 此方法还有问题,还是不能很好的解决变量名子串的问题,而且需要重新匹配的问题
  */
 public String replace2(String express, Map<String, String> replaceMap) {
  Iterator iter = replaceMap.entrySet().iterator();
  StringBuilder sb = new StringBuilder();
  String tail = "";

  while (iter.hasNext()) {
   Map.Entry<String, String> entry = (Map.Entry<String, String>) iter.next();
   String key = entry.getKey();
   String value = entry.getValue();

   sb.append(tail);
   sb.append(key);

   tail = "|";
  }

  Pattern p = Pattern.compile(sb.toString());
  Matcher m = p.matcher(express);
  StringBuffer result = new StringBuffer();
  while (m.find()) {

   String reg = m.group();

   int start = m.start();
   int end = m.end();

   if (start != 0
     && operators.indexOf(express.substring(start - 1, start)) == -1) {
    m.reset();
    m.region(start, express.length() - 1);
    continue;
   }

   if (end != express.length()
     && operators.indexOf(express.substring(end, end + 1)) == -1) {
    m.reset();
    m.region(start, express.length() - 1);
    continue;
   }

   m.appendReplacement(result, replaceMap.get(reg));
  }
  m.appendTail(result);

  return result.toString();
 }
 
 /**
  * 
  * @param express
  * @param replaceMap
  * @return
  * 
  * ^ 行的开头 
     * $ 行的结尾 
     * \b 单词边界 
     * \B 非单词边界 
     * \A 输入的开头 
     * \G 上一个匹配的结尾 
     * 
     * 比较好的解决方法,一次遍历替换全部的变量名
  */
 public String replace3(String express, Map<String, String> replaceMap) {
  Iterator iter = replaceMap.entrySet().iterator();
  StringBuilder sb = new StringBuilder();
  sb.append("([");
  sb.append(operators);
  sb.append("]+|\\G)(");
  String tail = "";
  while (iter.hasNext()) {
   Map.Entry<String, String> entry = (Map.Entry<String, String>) iter.next();
   String key = entry.getKey();
   String value = entry.getValue();

   sb.append(tail);
   sb.append(key);
   tail = "|";
  }
  sb.append(")([");
  sb.append(operators);
  sb.append("]+|$)");
  Pattern p = Pattern.compile(sb.toString());
  Matcher m = p.matcher(express);
  StringBuffer result = new StringBuffer();
  while (m.find()) {
   String reg = m.group(2);
   m.appendReplacement(result, m.group(1) + replaceMap.get(reg)
     + m.group(3));

  }
  m.appendTail(result);
  express = result.toString();

  return express;
 }
}





//ExpressionRegexTest.java

package com.ztianyi.regex;

import static org.junit.Assert.*;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.ztianyi.test.JavaCodeTest;

public class ExpressionRegexTest {

 private static final Log log = LogFactory.getLog(ExpressionRegexTest.class);
 
 @Before
 public void setUp() throws Exception {
 }

 @After
 public void tearDown() throws Exception {
 }

 @Test
 public void testReplace() {
  Map replaceMap = new HashMap();
  replaceMap.put("薪酬总额", "f1");
  replaceMap.put("项目工资", "f2");
  
  replaceMap.put("绩效工资(其他)", "f4");
  replaceMap.put("绩效工资", "f3");
  
  ExpressionRegex rm = new ExpressionRegex();
  
  String result = rm.replace("薪酬总额 =项目工资+绩效工资(其他)-(绩效工资 ", replaceMap);
  log.info(result);
  
  boolean b= Pattern.matches("([+\\-*/()&|=! ]+|^)(绩效工资)([+\\-*/()&|=! ]+|$)", "-绩效工资");
  log.info(b);
  
  Pattern p = Pattern.compile("([+\\-*/()&|=! ]+|^)(项目工资)([+\\-*/()&|=! ]+|$)|(([+\\-*/()&|=! ]+|^)(绩效工资)([+\\-*/()&|=! ]+|$))");
  Matcher m = p.matcher("薪酬总额 =项目工资+绩效工资(其他)+绩效工资+绩效工资");
  m.find();
  if(m.find())
  {
   log.info(m.groupCount());
   log.info(m.group(0));
   log.info(m.group(1));
   log.info(m.group(2));
   log.info(m.group(3));
   log.info(m.group(4));
   log.info(m.group(5));
   log.info(m.group(6));
   
  }
  
  p = Pattern.compile("([+\\-*/()&|=! ]+|^)(薪酬总额|项目工资|绩效工资)([+\\-*/()&|=! ]+|$)");
  m = p.matcher("薪酬总额 =项目工资+绩效工资(其他)+绩效工资+绩效工资");
  while(m.find())
  {
   log.info(m.groupCount());
   for(int i=0; i<=m.groupCount(); i++)
   {
    log.info(m.group(i));
   }
   
  }
  
  
 }

 @Test
 public void testMatch() {
  boolean b= Pattern.matches("([+\\-*/()&|=! ]+|^)(项目工资|绩效工资)([+\\-*/()&|=! ]+|$)", "绩效工资");
  log.info(b);
 }
 
 //@Test
 public void testReplace2() {
  Map replaceMap = new HashMap();
  replaceMap.put("薪酬总额", "f1");
  replaceMap.put("项目工资", "f2");
  replaceMap.put("绩效工资", "f3");
  //replaceMap.put("绩效工资(其他)", "f4");
  
  
  ExpressionRegex rm = new ExpressionRegex();
  
  String result = rm.replace2("薪酬总额 =项目工资+绩效工资(其他)-(绩效工资 ", replaceMap);
  log.info(result);
 }
 
 @Test
 public void testReplace3() {
  Map replaceMap = new HashMap();
  replaceMap.put("薪酬总额", "f1");
  replaceMap.put("项目工资", "f2");
  replaceMap.put("绩效工资", "f3");
  //replaceMap.put("(其他)绩效工资", "f4");
  
  
  ExpressionRegex rm = new ExpressionRegex();
  
  String result = rm.replace3("薪酬总额 =项目工资+(其他)绩效工资-(绩效工资 ", replaceMap);
  log.info(result);
 }
}
 
分享到:
评论

相关推荐

    易语言正则表达式文本替换

    例如,"子程序_正则文本替换"可能就是一个易语言中用于执行正则表达式替换的子程序,它接收输入的文本、正则表达式模式和替换字符串,然后返回经过替换操作的新文本。 1. **正则表达式基础** - **元字符**:如`.`...

    使用正则表达式验证中文汉字输入

    在本主题中,“使用正则表达式验证中文汉字输入”着重讲解如何利用正则表达式来确保用户输入的数据仅包含合法的中文汉字。 首先,我们需要了解中文汉字在计算机中的表示方式。中文字符在Unicode编码中占据着一定的...

    易语言正则表达式匹配中文

    在易语言中,正则表达式是进行文本处理、数据提取和搜索的关键工具,尤其在处理中文字符时显得尤为重要。本文将深入探讨易语言中的正则表达式匹配中文的原理、方法以及应用。 正则表达式(Regular Expression)是一...

    易语言正则表达式类匹配中文

    例如,对于一个新闻网站,可以利用正则表达式类匹配中文源码来提取文章标题或关键词,或者在用户输入的搜索查询中进行模糊匹配,提高搜索效率。 通过易语言提供的正则表达式类,我们可以高效地处理中文文本,进行...

    正则表达式统计汉字

    为了统计一个字符串中汉字的数量,我们需要构建一个能够匹配汉字的正则表达式。在 Unicode 编码下,汉字的范围大致位于 `\x{4e00}-\x{9fa5}` 区间内。因此,可以使用正则表达式 `[^\x{4e00}-\x{9fa5}]` 来匹配非汉字...

    正则表达式中文手册(图书).pdf

    后向引用是一种引用之前定义过的子表达式的能力,它在文本替换和模式匹配中非常有用。在某些编程环境(如.NET)中,后向引用的使用具有特定的语法规则。 正则表达式的文本替换功能允许用户通过查找符合特定模式的...

    正则表达式中文帮助文档.rar

    这个“正则表达式中文帮助文档”应该包含了正则表达式的详细解释、实例演示以及常见问题解答,可以帮助学习者更好地理解和运用正则表达式。通过阅读文档,你将能够了解更多的细节,比如如何在不同环境下使用正则,...

    RegexDesigner.NET 正则表达式开源工具 支持中文 修改版

    regexdesigner.net是一个强力的可视化工具,可以帮助我们构建与测试.NET正则表达式,RegexDesigner.NET让我们将我们开发出的正则表达式集成到我们的应用程序,可以方便的生成C#或VB.NET代码并编译成程序集 ...

    正则表达式汉字验证

    正则表达式是一种强大的文本处理工具,用于模式匹配、搜索和替换字符串中的特定字符或模式。在编程和脚本语言中广泛使用,特别是在文本数据的处理和验证中。本文将深入探讨如何使用正则表达式进行汉字验证,这是一个...

    支持含有中文变量名的表达式计算

    描述中指出,现有的计算表达式实现通常不支持中文变量名,而作者通过对一个计算器程序的源码进行修改,实现了这个功能。这涉及到的主要技术点包括字符串解析、词法分析、语法分析以及变量映射。 首先,字符串解析是...

    易语言源码正则表达式文本替换.7z

    易语言是一种专为中国人设计的编程语言,它以简体中文作为编程语句,降低了编程的门槛,使得更多的人能够参与到编程中来。本压缩包“易语言源码正则表达式文本替换.7z”提供了易语言实现的源代码,用于进行正则...

    VC++支持中文的正则表达式函数库

    在IT行业中,正则表达式(Regular Expression)是一种强大的文本处理工具,用于匹配、查找、替换和解析字符串。在C++编程环境下,虽然标准库没有内置的正则表达式支持,但开发人员经常通过第三方库来实现这一功能。...

    《正则表达式中文手册》

    ### 正则表达式中文手册知识点详述 #### 一、引言 正则表达式是一种强大而灵活的文本处理工具,广泛应用于多种编程语言中,用于文本的搜索、替换和提取等操作。掌握正则表达式的使用对于任何从事软件开发工作的人员...

    正则表达式只可以输入只允许输入中文、数字、字母、下划线

    正则表达式(Regular Expression)是一种强大的文本处理工具,在编程语言中被广泛应用于字符串的搜索与替换等操作。它能够帮助开发者快速定位、提取或验证文本中的模式。 #### 二、中文、数字、字母、下划线的匹配 ...

    C#正则提取中文

    在IT领域,特别是编程语言与文本处理中,正则表达式是一种极其强大的工具,用于模式匹配、搜索、替换以及提取特定格式的数据。在C#语言中,正则表达式的应用非常广泛,尤其在处理中文字符时,其灵活性和效率更是得到...

    Java 正则表达式判断字符串是否包含中文

    通过本文的学习,我们不仅了解了如何使用 Java 的正则表达式来判断一个字符串中是否包含中文字符,还深入了解了 Java 中正则表达式的相关 API 和基本原理。这对于从事 Java 开发的技术人员来说是非常实用且必要的...

    易语言源码正则表达式匹配中文.7z

    中文字符在正则表达式中可以单独写出来,或者使用Unicode范围来表示,如`\u4e00-\u9fff`代表所有基本的中文汉字范围。 3. **匹配操作**:调用易语言提供的正则函数,如`正则表达式匹配`或`正则表达式替换`,传入待...

    精通正则表达式(第三版)简体中文版

    本书《精通正则表达式(第三版)简体中文版》主要介绍了正则表达式的概念、语法以及如何在不同的环境中高效地使用正则表达式。 #### 二、正则表达式的语法基础 1. **元字符**:正则表达式中的特殊字符,用于指定...

    PB实现的正则表达式

    在IT领域,正则表达式(Regular Expression,简称regex)是一种强大的文本处理工具,它能够进行复杂的模式匹配、查找、替换等操作。在本话题中,我们将探讨如何使用PowerBuilder 11.5这一经典的开发环境来实现正则...

Global site tag (gtag.js) - Google Analytics