将任意 JavaScript 代码存储到字符串变量中

store arbitrary JavaScript code into a string variable

我有一个程序(用 Clojure 编写)将一些 JS 代码注入 JS 函数,然后通过 Nashorn 对其求值。我无法控制代码传递(它可能包含引号、简单引号...)。

看起来像这样:

;; Clojure
(eval-str (str "print(evaluateCode(\"" s  " \"))"))

// equivalent code in pseudo-js just for those not reading Clojure fluently
evalJS("println(evaluateCode(" + arbitraryJS + "))")

evaluateCode 函数已经加载。

// already loaded in Nashorn
function evaluateCode(code) {
   // do something with the code
   //...
   eval(code);
}

这适用于简单的程序,例如。如果 arbitraryJS = "var a=123; print(a); return a;".

但是一旦程序包含引号,它就会中断。前任。 "var a = 123; print("a is now", a);"

注:实际代码为there

您需要对字符串进行转义。在每个 " 之前放置一个 \。 如果你需要 \ 本身使用它双 \\

抱歉,我还不能发表评论... :/

我建议转义引号和反斜杠。我会选择单引号作为 JS 字符串分隔符,因为在 Clojure 中你必须使用双引号来分隔字符串:

;; Clojure
(eval-str (str "print(evaluateCode('"
               (clojure.string/replace s #"(['\\])" "\\")
               "'))"))

查找和替换模式各有四个反斜杠。因为在 Clojure 中反斜杠是一个转义字符,所以它们实际上只表示两个反斜杠。在正则表达式中,反斜杠 也是 一个转义字符,所以最后它们只表示一个,每个反斜杠。所以这意味着 "prefix any occurrence of backslash or quote with a backslash."

您不必担心注释和模板等问题,因为转义字符仅存在于 Clojure 中(替换后),但在 Javascript 引擎解析完整字符串时会被解析。 evaluateCode 函数永远不会看到转义字符,而是 s.

的普通值

例子

;; Clojure
(def s "a = 'test'; // 'test' used here")
(eval-str (str "print(evaluateCode('"
               (clojure.string/replace s #"(['\\])" "\\")
               "'))"))

这将计算为:

(eval-str "print(evaluateCode('a = \'test\'; // \'test\' used here'))")

请注意,在上述表示中反斜杠加倍,但这是因为 Clojure 需要它。实际字符串仅出现一次反斜杠。如果您不调用 eval-str,而是使用相同的参数调用 println,您将得到以下输出:

print(evaluateCode('a = \'test\'; // \'test\' used here'))

这是由 Javascript 引擎解释的字符串,因此它将反斜杠解释为转义字符,将干净的字符串传递给 evaluateCode.

所以如果 evaluateCode 看起来像这样:

function evaluateCode(code) {
   alert(code);
}

它会产生这个警报:

a = 'test'; // 'test' used here

因此,转义反斜杠在 Javascript 中根本不存在。它将看到与 Clojure 符号 s 所代表的完全相同的值。

后面我用了Apache Commons Lang StringUtils since the other solutions did not work. See it here.