编译
\documentclass{article}
\usepackage{etoolbox,xstring}
\newcommand{\strendswithfoo}{\IfEndWith{bar-foo}{foo}{true}{false}}
\newtoggle{strendswithfoo}
\settoggle{strendswithfoo}{\strendswithfoo}
\begin{document}
command \textbackslash strendswithfoo = \strendswithfoo
toggle strendswithfoo = \iftoggle{strendswithfoo}{true}{false}
\end{document}
导致以下错误:
./test.tex:7: Missing \endcsname inserted.
<to be read again>
\let
l.7 \settoggle{strendswithfoo}{\strendswithfoo}
The control sequence marked <to be read again> should
not appear between \csname and \endcsname.
./test.tex:7: Argument of \reserved@a has an extra }.
<inserted text>
\par
l.7 \settoggle{strendswithfoo}{\strendswithfoo}
I've run across a `}' that doesn't seem to match anything.
For example, `\def\a#1{...}' and `\a}' would produce
this error. If you simply proceed now, the `\par' that
I've just inserted will cause me to report a runaway
argument that might be the root of the problem. But if
your `}' was spurious, just type `2' and it will go away.
Runaway argument?
{\@firstoftwo {\let \@xs@assign \@xs@expand@and@detokenize \@xs@IfEndWith@@ \ETC.
./test.tex:7: Paragraph ended before \reserved@a was complete.
<to be read again>
\par
l.7 \settoggle{strendswithfoo}{\strendswithfoo}
I suspect you've forgotten a `}', causing me to apply this
control sequence to too much text. How can we recover?
My plan is to forget the whole thing and hope for the best.
./test.tex:7: Package etoolbox Error: Invalid boolean value '\let \reserved@d =*\def \par .
<recently read>
l.7 \settoggle{strendswithfoo}{\strendswithfoo}
Valid boolean values are 'true' and 'false'.
输出文档包含:
command \strendswithfoo = true
toggle strendswithfoo = false
我希望切换strendswithfoo
为真。如果有更好的解决方案,我很乐意放弃 xstring。
答案1
另一种方法是使用listofitems
,其结果是可扩展的。也就是说,实际\readlist
是不可扩展的,但它生成的数据数组是可扩展的。
在此实现中,我搜索测试字符串中所有出现的“foo”,并将其用作列表分隔符。不是“foo” 存储在\foosep
数组、、\foosep[1]
等中\foosep[2]
,其中索引1
是最左边“foo”左边的文本,索引2
是第 1 个和第二个“foo”之间的文本,等等。
负索引(例如)[-1]
仅从最右边的“foo”开始向左计数。如果字符串以“foo”结尾,则\foosep[-1]
表示最右边“foo”右侧文本的扩展将为空,因此我测试其是否为空以确定是否将切换设置为 true 或 false。
\documentclass{article}
\usepackage{etoolbox,listofitems}
\newtoggle{strendswithfoo}
\def\toggletmp{\settoggle{strendswithfoo}}
\newcommand{\teststrendswithfoo}[1]{%
\setsepchar{foo}%
\readlist\foosep{#1}%
\edef\strendswithfoo{\if\relax\foosep[-1]\relax{true}\else{false}\fi}%
\expandafter\toggletmp\strendswithfoo
}
\begin{document}
\teststrendswithfoo{bar-foo}
toggle strendswithfoo = \iftoggle{strendswithfoo}{true}{false}
\teststrendswithfoo{foo-bar}
toggle strendswithfoo = \iftoggle{strendswithfoo}{true}{false}
\end{document}
答案2
一种解决方案是将参数设为\IfEndWith
\toggletrue
和\togglefalse
。我发现这相当不令人满意,而且有点像意大利面条式的代码,虽然我喜欢,但它很短。
\documentclass{article}
\usepackage{etoolbox,xstring}
\newtoggle{strendswithfoo}
\IfEndWith{bar-foo}{foo}{\toggletrue}{\togglefalse}{strendswithfoo}
\begin{document}
toggle strendswithfoo = \iftoggle{strendswithfoo}{true}{false}
\end{document}