测试字符串的最后一个字母是否大写

测试字符串的最后一个字母是否大写

我想定义一个命令,使其根据输入的最后一个字符的性质做出反应。但我很难让命令的各个部分正常工作。

我以为我可以抓住细绳我传递命令并使用expl魔法将其变为大写。然后我会测试最后一个字母和它的大写版本是否相同。但我甚至无法做到这一点。

在这个 MWE 中,我定义了两个命令。第一个命令只是用来抓取第一个令牌并将其更改为大写。它无法做到这一点。第二个应该反转字符串并仅返回第一个标记。这也失败了。

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn

\tl_new:N \l_ae_lasttoken_tl
\tl_new:N \l_ae_upper_lasttoken_tl
\NewDocumentCommand{\aeupcasefirstelement}{ m }
    {
        \tl_set:Nn  \l_ae_lasttoken_tl        { \tl_head:n { #1 } }
        \tl_set:Nn  \l_ae_upper_lasttoken_tl  { \tl_to_uppercase:n {  \l_ae_lasttoken_tl } }
        %% show results of these actions
        \textbf{ \l_ae_lasttoken_tl {~   vs.  ~} \l_ae_upper_lasttoken_tl }
    }

\NewDocumentCommand{\aelastelement}{ m }
    {
        \tl_set:Nn \l_ae_lasttoken_tl { \tl_head:V { \tl_reverse:V #1 } }
        %% show results of these actions
        \textbf{ \l_ae_lasttoken_tl }
    }

\ExplSyntaxOff
\pagestyle{empty}
\setlength{\parindent}{0pt}
\begin{document}

\begin{tabular}{ll}
Expecting to see & Getting \\
\textbf{T vs. T} & \aeupcasefirstelement{This is a test of my command} \\
\textbf{t vs. T} & \aeupcasefirstelement{this is a test of my command} \\
\textbf{d}       & \aelastelement{This is a test of my command}
\end{tabular}

\end{document}

答案1

这定义了一个条件,测试标记列表中的最后一项是否为大写;标记列表应该仅由 ASCII 字符组成。

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\prg_new_protected_conditional:Npnn \ae_if_last_uc:n #1 { T , F , TF }
 {
  \tl_set:Nx \l_ae_testa_tl { \tl_item:nn { #1 } { -1 } }
  \tl_set:Nx \l_ae_testb_tl { \text_uppercase:V \l_ae_testa_tl }
  \tl_if_eq:NNTF \l_ae_testa_tl \l_ae_testb_tl
   { \prg_return_true: }
   { \prg_return_false: }
 }
\cs_generate_variant:Nn \text_uppercase:n { V }

% A test
\ae_if_last_uc:nTF { abc } { \typeout{UC} } { \typeout{LC} }
\ae_if_last_uc:nTF { abC } { \typeout{UC} } { \typeout{LC} }

\ExplSyntaxOff

\stop

测试输出

LC
UC

您的问题很常见:\tl_to_uppercase:n​​(即原始的\uppercase)不可扩展。


让我们看看你的宏。

\NewDocumentCommand{\aeupcasefirstelement}{ m }
 {
  \tl_set:Nn \l_ae_lasttoken_tl        { \tl_head:n { #1 } }
  \tl_set:Nn \l_ae_upper_lasttoken_tl  { \tl_to_uppercase:n {  \l_ae_lasttoken_tl } }
  %% show results of these actions
  \textbf{ \l_ae_lasttoken_tl {~   vs.  ~} \l_ae_upper_lasttoken_tl }
 }

\aeupcasefirstelement{abc}存储在\l_ae_lasttoken_tl代币中\tl_head:n{a},在\l_ae_upper_lasttoken_tl代币中

\tl_to_uppercase:n{\l_ae_lasttoken_tl}

这肯定不是你想要的。打印结果似乎是正确的,这纯属偶然,因为在排版过程中,TeX 会扩展并执行标记。为了存储第一个项目,\l_ae_lasttoken_tl你需要扩张函数\tl_item:nn,因此使用

\tl_set:Nx \l_ae_lasttoken_tl { \tl_item:nn { #1 } }

是正确的习惯用法。对于大写,您必须\text_uppercase:n像我上面所做的那样,或者以不同的间接方式进行大写:

\exp_args:Nx \tl_to_uppercase:n
 {
  \exp_not:n { \tl_set:Nn \l_ae_lasttoken_uppercase_tl } { \l_ae_lasttoken_tl }
 }

\tl_to_uppercase:x(当然,定义一个变体会更好)。

最大的问题是\tl_to_uppercase:n无法扩展,并且工作方式很奇怪。另请注意,\tl_to_uppercase:n不再存在于中expl3,因为它的奇怪之处和工作方式与代码范围不符expl3

答案2

这将抓取最后一个字符并将其填充到 中\lastchar。然后将该字符大写并将其填充到 中\uplastchar。然后,一个简单的操作\if就会区分。

\documentclass{article}
\usepackage{stringstrings}
\begin{document}
\def\strng{This is a test of the emergency broadcast system}
\strng

\substring[q]{\strng}{$}{$}
\edef\lastchar{\thestring}

\caseupper[q]{\thestring}
\edef\uplastchar{\thestring}

\lastchar~\uplastchar

\if\lastchar\uplastchar SAME\else DIFFERENT\fi

\end{document}

ps 一般来说,字符串不能包含宏,但如果有必要,也有各种例外和一些解决方法。

答案3

另一个要探索的可能性是pdfTeX原始的\pdfmatch。宏\islastcap检查字符串中最后一个字母的状态,忽略其他字符。

\def\islastcap#1{%
\ifnum\pdfmatch subcount 1 {[A-Z][^a-zA-Z]*$}{#1}=1 %
[U] \else [L] \fi \ #1}

\def\str{ arl kdS   }  

\islastcap{\str}

\islastcap{\str a  }

\islastcap{\str .  }

\islastcap{\str . Y;  }

\islastcap{\str . Yn/T/f/;  }

\bye

输出:

[U] arl kdS
[L] arl kdS a
[U] arl kdS .
[U] arl kdS . Y;
[L] arl kdS . Yn/T/f/;

相关内容