我很抱歉,这个问题可能看起来与我最近问过的其他几个问题非常相似(解析前导硬空格,将 \$ 解析为改进的 \getargs 命令的一部分)。它们都与使用递归技术解析字符串有关。David Carlisle 在前面的查询中已经给了我很大的帮助,他指出了如何\protected@edef
处理特殊\$
字符(例如),并使用\let
将硬空格重新定义为无害的内容(空值或软空格)。
但现在我发现算法在变音符号(\"u
)等变音符号上会卡住。我猜这些不是“字符”,而是可扩展的“宏”,这也许可以解释为什么逐个字符搜索的算法可能会卡住。所以我在寻找一个聪明的解决方法,比如临时\let
或\catcode
重新定义,这样算法就可以消化这些类型的“字符”。
代码如下。我注释掉了一行(倒数第二行),这会导致算法阻塞。算法所做的是查看参数并将其解析为单个单词。它将第一个单词放在 中\argi
,将第二个单词放在 中\argii
,等等,并将单词总数放在 中\narg
。它比包中的前身快得多stringstrings
。它可以很好地处理字母数字输入、特殊字符、硬空格和软空格,但(目前)还不能处理变音符号。
\documentclass{article}
\makeatletter
\usepackage{ifnextok}
\usepackage{ifthen}
\def\string@end{$}
\def\converttilde{T}
\newcounter{arg@index}
\let\SaveHardspace~
\def\getargsF#1{%
\if T\converttilde\def~{ }\fi%
\protected@edef\the@string{#1}%
\def\argi{}\setcounter{arg@index}{1}%
\expandafter\parse@Block\the@string\string@end%
\let~\SaveHardspace%
}
%ifthenelse needed when leading spaces end up as \argi
\def\parse@Block{\IfNextToken\string@end%
{\edef\narg{\arabic{arg@index}}\@gobble}%
{\IfNextToken\@sptoken{\addtocounter{arg@index}{1}%
\ifthenelse{\equal{\argi}{}}{\addtocounter{arg@index}{-1}}{}%
\expandafter\def\csname arg\roman{arg@index}\endcsname{}%
\add@to{\parse@Block}}%
{\add@to{\parse@Block}}}}
\def\add@to#1#2{\if\@sptoken#2\else\expandafter\protected@edef%
\csname arg\roman{arg@index}\endcsname%
{\csname arg\roman{arg@index}\endcsname#2}\fi#1}
\makeatother
\begin{document}
\getargsF{mein hut} \argi~\argii $<$NO PROBLEM\\
BUT PUT UMLAUT ON THE u AND IT BREAKS
%\getargsF{mein h\"ut} \argi~\argii
\end{document}
答案1
一旦你用 扩展了原始输入中的所有内容,\protected@edef
你就不需要逐个标记地逐个标记地处理,这使得处理任何类型的括号组或带参数的命令变得困难。这只需使用分隔参数进行扫描以查找空格,这要简单得多。
\documentclass{article}
\makeatletter
\def\string@end{$\SaveHardspace}
\def\converttilde{T}
\newcounter{arg@index}
\let\SaveHardspace~%%%
\def\getargsF#1{%
\if T\converttilde\def~{ }\fi
\protected@edef\the@string{#1}%
\setcounter{arg@index}{0}%
\lowercase{\expandafter\parse@Block\the@string} \string@end
\let~\SaveHardspace
}
\def\parse@Block#1 {%
\stepcounter{arg@index}%
\@namedef{arg\roman{arg@index}}{#1}%
\futurelet\tmp\parse@Block@}
\def\parse@Block@{%
\ifx\tmp\string@end\edef\narg{\thearg@index}\expandafter\@gobble
\else\expandafter\parse@Block\fi}
\makeatother
\begin{document}
\getargsF{mein hut} \argi~\argii~[\narg] $<$ NO PROBLEM
BUT PUT UMLAUT ON THE u AND IT BREAKS
\getargsF{mein h\"ut see} \argi~\argii~[\narg]
\end{document}
答案2
以下内容与上面描述的输入相关。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\getargs}{m}{
\get_args:n {#1}
}
\int_new:N \narg
\cs_new_protected:Npn \get_args:n #1 {
\seq_set_split:Nnn \l_tmpa_seq {~} {#1}
\seq_map_inline:Nn \l_tmpa_seq {
\int_incr:N \l_tmpa_int
\tl_set:cx {arg\int_to_roman:n {\l_tmpa_int}}{##1}
}
\int_set:Nn \narg {\l_tmpa_int}
\int_zero:N \l_tmpa_int
}
\ExplSyntaxOff
\begin{document}
\getargs{mein hut} \argi~\argii $<$NO PROBLEM\\
BUT PUT UMLAUT ON THE u AND IT BREAKS
\getargs{mein h\"ut} \argi~\argii
\end{document}
答案3
这是一个无需扩展、能够解析宏和组的解决方案{...}
:
\documentclass{article}
\makeatletter
\newcount\arg@index
\newtoks\code@toks
\def\getargsF#1{%
\arg@index=1
\code@toks{}%
\parse@i#1\parse@stop
}
\def\add@tok#1{\code@toks\expandafter{\the\code@toks#1}}
\def\parse@stop{\parse@stop}
\def\parse@i{\futurelet\nxttok\parse@ii}
\def\parse@ii{%
\ifx\nxttok\parse@stop \let\next@action\parse@stop@i
\else
\ifx\nxttok\@sptoken \let\next@action\read@space
\else
\ifx\nxttok\bgroup \let\next@action\read@bracearg
\else \let\next@action\testtoken
\fi
\fi
\fi
\next@action
}
\def\parse@stop@i\parse@stop{\assign@arg}
\expandafter\def\expandafter\read@space\space{%
\assign@arg
\advance\arg@index1
\code@toks{}%
\parse@i
}
\def\read@bracearg#1{%
\add@tok{{#1}}%
\parse@i
}
\def\testtoken#1{%
\if\noexpand~\noexpand#1%
\ifnum\catcode`#1=\active
\assign@arg
\advance\arg@index1
\code@toks{}%
\else
\add@tok{#1}%
\fi
\else
\add@tok{#1}%
\fi
\parse@i
}
\def\assign@arg{%
\expandafter\edef\csname arg\romannumeral\arg@index\endcsname{\the\code@toks}%
}
\makeatother
\begin{document}
\getargsF{abcd efgh~h\"ut}\argi\#\argii\#\argiii\#
\getargsF{maths $1+1=2$ \textbf{b\textit{ol}d} \^a\'i\'o~hardspc~end}\argi\#\argii\#\argiii\#\argiv\#\argv\#\argvi\#
\catcode`\~12
\getargsF{maths $1+1=2$ \textbf{b\textit{ol}d} \^a\'i\'o~hardspc~end}\argi\#\argii\#\argiii\#\argiv\#
\end{document}
这使