WRe*_*ach 11 wolfram-mathematica
如何将从单元格表达式中提取的任意框规范转换为输入表达式?
这是我在FullForm语法中对Save Mathematica代码的回答.在该上下文中,模式匹配被用于从使用读取的笔记本表达式中提取框规范Import.
我认为ToExpression或者MakeExpression会做盒子解释的工作,但在某些情况下他们没有.
考虑一个包含表达式的输入单元格:
StringForm["a = ``", 1]
Run Code Online (Sandbox Code Playgroud)
这种细胞的细胞表达如下:
Cell[BoxData[
RowBox[{"StringForm", "[",
RowBox[{"\"\<a = ``\>\"", ",", " ", "1"}], "]"}]], "Input"]
Run Code Online (Sandbox Code Playgroud)
我可以BoxData从这个单元格ToExpression中获取子表达式并使用获取相同的输出,就像我评估原始单元格一样:
ToExpression @
BoxData[
RowBox[{"StringForm", "[",
RowBox[{"\"\<a = ``\>\"", ",", " ", "1"}], "]"}]]
Run Code Online (Sandbox Code Playgroud)
但现在考虑以下输入表达式:
StringForm["a = ``", 1]
你必须仔细观察才能发现差异:a用斜体字表示.这是相应的单元格表达式:
Cell[BoxData[
RowBox[{"StringForm", "[",
RowBox[{"\"\<\!\(\*
StyleBox[\"a\",
FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]], "Input"]
Run Code Online (Sandbox Code Playgroud)
如果我正常评估这个单元格,我会得到预期的结果.但是,如果我尝试应用ToExpression到BoxData像以前一样的子表达式:
ToExpression @
BoxData[
RowBox[{"StringForm", "[",
RowBox[{"\"\<\!\(\*
StyleBox[\"a\",
FontSlant->\"Italic\"]\) = ``\>\"", ",", " ", "1"}], "]"}]]
Run Code Online (Sandbox Code Playgroud)
发生错误:
StringForm::string : String expected at position 1 in StringForm[]\) = '',
FontSlant->"\~\(\*\nStyleBox["a Italic, 1].
Run Code Online (Sandbox Code Playgroud)
对于许多(如果不是全部)内联字符串框转义序列,会发生同样的错误.我已经尝试明确指定表单ToExpression和MakeExpression,但我得到相同的错误.这让我想到了我的问题......
我需要做些什么才能模仿Mathematica从输入单元格表达式解释方框的方式?
我认为这是一个错误.以下是我测试过的几个例子的解决方法:
Clear[toExpression];
toExpression[bd_BoxData] :=
ToExpression[bd /.
s_String :>
StringReplace[
StringReplace[s, "\n" :> ""],
ShortestMatch[(start : "\(\*") ~~ body__ ~~ (end : "\)")] :>
StringJoin[start, StringReplace[body, "\"" :> "\\\""], end]
]
];
Run Code Online (Sandbox Code Playgroud)
例如,我们从您的案例开始:
In[747]:=
BoxData["\"\<\!\(\*
StyleBox[\"a\",
FontSlant->\"Italic\"]\) = ``\>\""]//toExpression
Out[747]= a = ``
Run Code Online (Sandbox Code Playgroud)
如果我们现在检查单元格,它是:
BoxData["\<\"\\!\\(\\*StyleBox[\\\"a\\\",FontSlant->\\\"Italic\\\"]\\)\ = ``\"\>"]
Run Code Online (Sandbox Code Playgroud)
代替
BoxData["\"\<\!\(\*StyleBox[\"a\",FontSlant->\"Italic\"]\) = ``\>\""]
Run Code Online (Sandbox Code Playgroud)
(这是删除换行符的初始版本).而且,我认为,这应该是从一开始就应该有的.现在:
In[746]:= ToExpression@
BoxData["\<\"\\!\\(\\*StyleBox[\\\"a\\\",FontSlant->\\\"Italic\\\"]\\) = ``\"\>"]
Out[746]= a = ``
Run Code Online (Sandbox Code Playgroud)
所以这已经很好了.
我不知道这项工作有多普遍,但它似乎适用于我尝试过的例子.主要的问题是,当一个像"字符串化"的东西a和Italic,它应该是\\\"a\\\"和\\\"Italic\\\"而不是\"a\"和\"Italic\"-为逃逸本身逃逸人失踪.