【问题标题】:Parse string containing javascript解析包含 javascript 的字符串
【发布时间】:2020-03-09 11:16:50
【问题描述】:

我有一个字符串:

2 + 2 = ${2 + 2}
This is a ${"string"}
This is an object: ${JSON.stringify({a: "B"})}
This should be "<something>": ${{
    abc: "def",
    cba: {
        arr: [
            "<something>"
        ]
    }

}.cba.arr[0]}
This should ${"${also work}"}

解析后我应该得到类似的东西:

2 + 2 = 4
This is a string
This is an object: {"a":"B"}
This should be "<something>": <something>
This should ${also work}

所以我需要帮助实现它用Java,我只需要得到${} 之间的内容。

我尝试使用正则表达式:\${(.+?)},但是当里面的字符串包含}时它会失败

【问题讨论】:

  • 正则表达式不是嵌套括号的最佳选择。
  • 那你有什么建议?
  • 你试过什么?什么没用?你得到了什么?你期待什么?什么不适用于您的代码,它在哪里?
  • 其中一种方法是使用递归正则表达式(这也不是很好,但如果你没有太多嵌套结构就可以了)。而且也不确定java正则表达式引擎是否支持递归regex101.com/r/pFEV5j/1
  • 是的,在 Java 中不起作用 (java.util.regex.PatternSyntaxException: Unknown inline modifier near index 18)。此外,当 ${ 和 } 之间有换行符时,您的正则表达式也不起作用

标签: java regex rhino


【解决方案1】:

所以经过一些测试,我最终得到了这个:

ScriptEngine scriptEngine = new ScriptEngineManager(null).getEngineByName("JavaScript");
String str = "2 + 2 = ${2 + 2}\n" +
        "This is a ${\"string\"}\n" +
        "This is an object: ${JSON.stringify({a: \"B\"})}\n" +
        "This should be \"F\": ${var test = {\n" +
        "    a : {\n" +
        "        c : \"F\"\n" +
        "    }\n" +
        "};\n" +
        "test.a.c\n" +
        "}\n" +
        "This should ${\"${also work}\"}"; // String to be parsed
StringBuffer result = new StringBuffer();
boolean dollarSign = false;
int bracketsOpen = 0;
int beginIndex = -1;
int lastEndIndex = 0;
char[] chars = str.toCharArray();
for(int i = 0; i < chars.length; i++) { // i is for index
    char c = chars[i];
    if(dollarSign) {
        if(c == '{') {
            if(beginIndex == -1) {
                beginIndex = i + 1;
            }
            bracketsOpen++;
        } else if(c == '}') {
            if(bracketsOpen > 0) {
                bracketsOpen--;
            }
            if(bracketsOpen <= 0) {
                int endIndex = i;
                String evalResult = ""; // evalResult is the replacement value
                try {
                    evalResult = scriptEngine.eval(str.substring(beginIndex, endIndex)).toString(); // Using script engine as an example; str.substring(beginIndex, endIndex) is used to get string between ${ and }
                } catch (ScriptException e) {
                    e.printStackTrace();
                }
                result.append(str.substring(lastEndIndex, beginIndex - 2));
                result.append(evalResult);
                lastEndIndex = endIndex + 1;
                dollarSign = false;
                beginIndex = -1;
                bracketsOpen = 0;
            }
        } else {
            dollarSign = false;
        }
    } else {
        if(c == '$') {
            dollarSign = true;
        }
    }
}
result.append(str.substring(lastEndIndex));
System.out.println(result.toString());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2012-05-04
    • 1970-01-01
    • 2012-11-09
    • 1970-01-01
    • 2020-04-28
    • 2011-12-19
    相关资源
    最近更新 更多