![일부 xstring 명령을 중첩하면 오류가 발생하는 이유는 무엇입니까?](https://rvso.com/image/405343/%EC%9D%BC%EB%B6%80%20xstring%20%EB%AA%85%EB%A0%B9%EC%9D%84%20%EC%A4%91%EC%B2%A9%ED%95%98%EB%A9%B4%20%EC%98%A4%EB%A5%98%EA%B0%80%20%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94%20%EC%9D%B4%EC%9C%A0%EB%8A%94%20%EB%AC%B4%EC%97%87%EC%9E%85%EB%8B%88%EA%B9%8C%3F.png)
왜 일부 명령을 결합합니까?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}