我想要一个命令来检查字符串是否是测量值,例如1cm
。检查字符串是否包含cm
似乎很容易出错。我似乎记得在某个地方看到过某人做过的例子,但我找不到它。
\documentclass{article}
\usepackage{xparse}
\NewDocumentCommand{\IsMeasurement}{m}{
% magic
}
\begin{document}
\IsMeasurement{1pt} % should output true, yes, 1, or similar
\IsMeasurement{1ptolemy} % should output false, no, 0, or similar
\end{document}
我当前的方法是测试最后两个字符,就像这样,并希望不会出现产生误报的情况:
\NewDocumentCommand{\LastTwo}{m}{%
\tl_item:nn { #1 } { -2 }%
\tl_item:nn { #1 } { -1 }%
}
\NewDocumentCommand{\IsMeasurement}{m}{
\str_case:nnF { #1 } {
{ cm } { 1 }
{ mm } { 1 }
{ pt } { 1 }
} { 0 }
}
\begin{document}
\IsMeasurement{cm} % works
\LastTwo{22cm} % outputs cm, as desired
\IsMeasurement{\LastTwo{cm}} % doesn't work
\end{document}
答案1
您可以查看输入是否与正则表达式匹配。
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\islengthTF}{mmm}
{
\mjc_islength:enn { #1 } { #2 } { #3 }
}
\cs_new_protected:Nn \mjc_islength:nnn
{
\regex_match:nnTF
{
\A % whole token list
[-+]?((\d+\.?\d*)|(\.\d+)) % a number https://stackoverflow.com/a/42629198/923955
\s* % optional spaces
(sp|pt|bp|dd|pc|cc|mm|cm|in) % legal TeX units
\Z % whole token list
}
{ #1 }
{ #2 } % it matches
{ #3 } % no match
}
\cs_generate_variant:Nn \mjc_islength:nnn { e }
\ExplSyntaxOff
\newcommand{\mylength}{12pt}
\begin{document}
\islengthTF{\mylength}{TRUE}{FALSE} (true)
\islengthTF{12pt}{TRUE}{FALSE} (true)
\islengthTF{12ptolemy}{TRUE}{FALSE} (false)
\islengthTF{.12cm}{TRUE}{FALSE} (true)
\islengthTF{..12cm}{TRUE}{FALSE} (false)
\islengthTF{2.1 in}{TRUE}{FALSE} (true)
\islengthTF{-2. cm}{TRUE}{FALSE} (true)
\end{document}
描述:
\A
代表“输入开始”[-+]?
-
表示其中零个或一个字符+
\d+\.?\d*
表示一个或多个数字,后面可以跟一个句点和其他数字\.d+
表示句点后跟一个或多个数字\s*
表示可选空格(sp|...|in)
在合法的单位双字母符号中查找一个\Z
代表“输入结束”
实际上,该部分(\.\d+)
可能是(\.d*)
因为.cm
在 TeX 中表示零厘米是合法的。我们不要太深奥。同样,TeX 允许在开头使用任意数量的可选符号,但在你的情况下,这似乎不值得允许。