首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

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

2013-09-11 
表达式中中文替换的问题(一)在EAS HR模块的薪酬部分,用户可以自定义薪酬的公式,公式中变量名就是薪酬项目

表达式中中文替换的问题(一)
在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.javapackage 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.javapackage 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); }} 

我的异常网推荐解决方案:软件开发者薪资,http://www.myexception.cn/other/1391128.html

热点排行