解析包含变音符号(宏?)的字符串

解析包含变音符号(宏?)的字符串

我很抱歉,这个问题可能看起来与我最近问过的其他几个问题非常相似(解析前导硬空格将 \$ 解析为改进的 \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}

这使

在此处输入图片描述

相关内容