如果参数的最后一个字符是 's',则删除它

如果参数的最后一个字符是 's',则删除它

我有一个语义注​​释\monster来注释怪物的提及,以便对它们进行索引:

\newcommand{\indexMonster}[1]{\index{#1}}
\newcommand{\monster}[1]{#1\indexMonster{#1}}

现在,大多数怪物的提及都是复数,但有些不是。我希望索引条目是单数。所以我正在寻找一种方法来删除参数的最后一个字符,\monster如果它是's'

答案1

此解决方案使用xstring。由于有一些可怕的怪物名叫信天翁这些都是非常可怕的,你当然会写很多关于它们的内容,我还制作了一个警告系统,用于在怪物名称发生变化时发出警告。当然,如果你愿意,你可以放弃它。如果你想覆盖以 结尾的怪物的测试s,只需在怪物周围添加括号,如下例所示。

输出 在此处输入图片描述

代码

\documentclass[11pt,draft]{article}
\usepackage{xstring}
\usepackage{ifdraft}
\newcommand{\indexMonster}[1]{\index{#1}}
\newcommand{\monster}[1]{%
    \IfEndWith{#1}{s}{%
    % Do nothing if ends with s.
    \StrGobbleRight{#1}{1}[\result]%
    \result\indexMonster{\result}%
    % Issue a warning on changed monsters
    \ifdraft{%
    \marginpar{Monster \textbf{#1} was changed to \result.}%
    }{}%%
    }{%
    #1\indexMonster{#1}}%
    }
\begin{document}
\monster{Dogs} \monster{Dog} \monster{albatross} \monster{{albatross}}
\end{document}

第二种解决方案

这是我对此的尝试expl3。我只是进行了文本替换,而不是索引,但这应该是微不足道的。

\documentclass[11pt]{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\monster}{m}
 {
  \l_wilx_monster:n { #1 }
 }

\cs_new_protected:Nn \l_wilx_monster:n
 {
    % Check if last character is "s"
    \str_if_eq_x:nnTF { \str_item:nn {#1} {-1} } {s} 
        % True: print string expect for last string (in other words, remove s)
        {\str_range:nnn {#1} {1} {-2}} %
        % False: Print string as usual
        {#1}
 }
\ExplSyntaxOff

\begin{document}
\monster{dogs}
\end{document}

答案2

下面是一个使用 TeX 基元去除最后一个元素的示例s。可展开的宏\striplastS已创建。\striplastS{texts}展开为text\striplastS{text}展开为text也。

\def\striplastS#1{\striplastSa{#1}#1\end s\end\eend}
\def\striplastSa#1#2s\end#3\eend{\ifx\end#3\end#1\else#2\fi}

%test:
\message{\striplastS{text} \striplastS{texts}} % prints: text text

答案3

您可以使用stringstringsSteven B. Segletes 的软件包:

\documentclass{article}
\usepackage{stringstrings}
\usepackage{makeidx}\makeindex

\begin{document}

\newcommand{\indexMonster}[1]{%
       \testmatchingchar{#1}{$}{s}
       \ifmatchingchar
          \substring[q]{#1}{1}{$-1}\index{\thestring}
        \else
          \index{#1}
       \fi}
\newcommand{\monster}[1]{#1\indexMonster{#1}}

\monster{zombies}

\pagebreak

\monster{zombie}

\printindex

\end{document}

在此处输入图片描述

答案4

你遇到的问题比你想象的还要多。

\documentclass{book}

\usepackage{etoolbox}
\usepackage{imakeidx}
\usepackage{fancyhdr}

\makeindex[name=monsters,title=Monster index]

\newcommand{\indexMonster}[1]{\index[monsters]{\stripfinals{#1}}}
\newrobustcmd{\monster}[1]{#1\indexMonster{#1}}
\makeatletter % Wipet's
\newcommand{\stripfinals}[1]{\strip@final@s{#1}#1\@nnil s\@nnil\@nil}
\def\strip@final@s#1#2s\@nnil#3\@nil{%
  \ifx\@nnil#3\@nnil#1\else#2\fi
}

% we don't want monster to be indexed also in the table of contents
% or in headers
\newcommand{\fixmonster}{\let\monster\@firstofone}
\patchcmd{\addtocontents}
 {\let}
 {\fixmonster\let}
 {}{}
\makeatother

\pagestyle{fancy}
\fancyhf{}
\fancyhead[LE,RO]{\thepage}
\makeatletter
\fancyhead[RE]{\fixmonster\leftmark}
\fancyhead[LO]{\fixmonster\rightmark}

\newcommand{\WviiSPOT}{\mbox{\monster{*S~P~O~T*}}}

\begin{document}

\frontmatter
\tableofcontents

\mainmatter

\chapter{\monster{zombies} and \WviiSPOT}

\monster{asasas}, \monster{zombies} and \WviiSPOT

\clearpage

\monster{zombie} and \monster{uss}

\printindex[monsters]

\end{document}

在此处输入图片描述

相关内容