为什么将一些命令组合起来xstring 包导致错误?例如当我编译以下 MWE 时:
\documentclass{article}
\usepackage{xstring}
\begin{document}
\section{A}
\StrCompare{\StrChar{bbbb}{4}}{\StrChar{aaaa}{3}}% are 4th character of first argument with 3th character of second argument differ ---> result 1 (yes and in first position)
\end{document}
它返回错误:
! Undefined control sequence.
\xs_StrChar__ ...ef \xs_arg_ii {#2}\edef \xs_call
{\noexpand \xs_testopt {\n...
l.5 ...mpare{\StrChar{bbbb}{4}}{\StrChar{aaaa}{3}}
% are 4th character of fir...
?
答案1
这是使用中一个相当常见的问题,xstring
因为(大多数)它的命令在仅扩展上下文中不起作用(在或\edef
或\expanded
或\write
...内),因此每个命令必须在下一个命令开始之前完全执行。简而言之,它们不能嵌套。一个可以显示相同问题的更简单示例是定义:
\newcommand\ifequal[2]{%
\def\tempa{#1}%
\def\tempb{#2}
\ifx\tempa\tempb
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi}
然后使用里面的命令\edef
:
\edef\test{\ifequal{abc}{abc}{true}{false}}
这将引发错误:
! Undefined control sequence.
\ifequal #1#2->\def \tempa
{#1}\def \tempb {#2} \ifx \tempa \tempb \expandaf...
l.13 \edef\test{\ifequal{abc}{abc}
{true}{false}}
?
然而如果你在外面使用它它\edef
就会起作用。
为了允许在另一个命令中使用一个命令的结果xstring
,大多数命令都有一个最终可选参数,它是一个用于存储处理结果的宏,然后您需要分别执行每个步骤并在每个步骤收集结果:
\documentclass{article}
\usepackage{xstring}
\begin{document}
\section{A}
\StrChar{bbbb}{4}[\tempA]
\StrChar{aaaa}{3}[\tempB]
\StrCompare{\tempA}{\tempB}
\end{document}
希望很快我能完成我的可扩展版本xstring
;-)
答案2
您不能\StrChar
在 的论点中使用\StrCompare
。
这里有两个实现:一个是xparse
和expl3
,一个是xstring
。请注意,前者是完全可扩展的,而后者则不是。
\documentclass{article}
\usepackage{xparse}
\usepackage{xstring} % for comparison
\ExplSyntaxOn
\NewExpandableDocumentCommand{\comparestringitems}{mmmmmm}
{
% #1 = first string
% #2 = item number
% #3 = second string
% #4 = item number
% #5 = true text
% #6 = false text
\str_if_eq:eeTF { \str_item:nn { #1 } { #2 } } { \str_item:nn { #3 } { #4 } } { #5 } { #6 }
}
\prg_generate_conditional_variant:Nnn \str_if_eq:nn { ee } { TF,T,F,p }
\ExplSyntaxOff
\newcommand{\comparestringitemsxstring}[6]{%
\StrChar{#1}{#2}[\compareA]%
\StrChar{#3}{#4}[\compareB]%
\StrCompare{\compareA}{\compareB}[\compareC]
\ifnum\compareC=0 #5\else#6\fi
}
\begin{document}
\comparestringitems{aaaa}{4}{bbbb}{3}{true}{false}
\comparestringitems{aaaa}{4}{bbab}{3}{true}{false}
\comparestringitemsxstring{aaaa}{4}{bbbb}{3}{true}{false}
\comparestringitemsxstring{aaaa}{4}{bbab}{3}{true}{false}
\edef\test{\comparestringitems{aaaa}{4}{bbab}{3}{true}{false}}
\texttt{\meaning\test}
\end{document}
通过简单的修改,您还可以将宏传递给\comparestringitems
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\comparestringitems}{mmmmmm}
{
% #1 = first string
% #2 = item number
% #3 = second string
% #4 = item number
% #5 = true text
% #6 = false text
\str_if_eq:eeTF { \str_item:en { #1 } { #2 } } { \str_item:en { #3 } { #4 } } { #5 } { #6 }
}
\prg_generate_conditional_variant:Nnn \str_if_eq:nn { ee } { TF,T,F,p }
\cs_generate_variant:Nn \str_item:nn { e }
\ExplSyntaxOff
\newcommand{\strA}{aaaa}
\newcommand{\strB}{bbbb}
\newcommand{\strC}{bbab}
\begin{document}
\comparestringitems{\strA}{4}{\strB}{3}{true}{false}
\comparestringitems{\strA}{4}{\strC}{3}{true}{false}
\edef\test{\comparestringitems{\strA}{4}{\strC}{3}{true}{false}}
\texttt{\meaning\test}
\end{document}