我正在尝试根据变量字符串中某个字符的计数来执行特定操作。
StrCount
当在 中使用 的结果时ifnumgreater
,尽管值被正确处理,但仍然出现错误。
我认为它StrCount
没有被处理为整数,但它确实输出了正确的值(之后2¿2
似乎是一个错误)。
有什么想法可以解决这个问题吗?
平均能量损失
\documentclass[draft]{article}
\usepackage{mwe}
\usepackage{etoolbox}
\usepackage{xstring}
\newcommand{\foo}{\StrCount{test}{t}}
\newcommand{\res}{}
\ifnumgreater{\foo}{0}{
\renewcommand{\res}{yes}
}{\renewcommand{\res}{no}}
\begin{document}
\res
\end{document}
输出
错误日志
./test.tex:7: Missing number, treated as zero.
<to be read again>
\let
l.7 \ifnumgreater{\foo}{2}
{
A number should have been here; I inserted `0'.
(If you can't figure out why I needed to see a number,
look up `weird error' in the index to The TeXbook.)
答案1
这是通常的问题,\StrCount{test}{t}
不是数字 1,而是一组最终(但不可扩展)产生它的复杂指令。
该xstring
包允许使用尾随可选参数,该参数应包含定义为扩展为操作结果的控制序列。
\documentclass{article}
\usepackage{etoolbox}
\usepackage{xstring}
\newcommand{\foo}{}% just for checking it's not defined
\StrCount{test}{t}[\foo]% this stores the number of matches in \foo
\newcommand{\res}{}
\ifnumgreater{\foo}{0}
{\renewcommand{\res}{yes}}
{\renewcommand{\res}{no}}
\begin{document}
\res
\end{document}
使用的变化xparse
,但精确的编码取决于您计划如何使用宏的信息。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\florian}{mmmO{}}
{% #1 = regex to test for
% #2 = token list
% #3 = cases
% #4 = default
\regex_count:nxN { #1 } { #2 } \l_florian_matches_int
\int_case:nnF { \l_florian_matches_int } { #3 } { #4 }
}
\int_new:N \l_florian_matches_int
\cs_generate_variant:Nn \regex_count:nnN { nx }
\ExplSyntaxOff
\newcommand{\testA}{test}
\newcommand{\testB}{tes}
\newcommand{\testC}{es}
\newcommand{\testD}{ttest}
\newcommand{\res}{} % initialize
\begin{document}
\florian{t}{\testA}{
{0}{\renewcommand{\res}{no}}
{1}{\renewcommand{\res}{yes, one}}
}[\renewcommand{\res}{yes, many}]
1. \res
\florian{t}{\testB}{
{0}{\renewcommand{\res}{no}}
{1}{\renewcommand{\res}{yes, one}}
}[\renewcommand{\res}{yes, many}]
2. \res
\florian{t}{\testC}{
{0}{\renewcommand{\res}{no}}
{1}{\renewcommand{\res}{yes, one}}
}[\renewcommand{\res}{yes, many}]
3. \res
\florian{t}{\testD}{
{0}{\renewcommand{\res}{no}}
{1}{\renewcommand{\res}{yes, one}}
{3}{\renewcommand{\res}{Three!}}
}[\renewcommand{\res}{yes, many}]
4. \res
\end{document}
答案2
为软件包量身定制listofitems
,提供完全可扩展的结果。在下面的 MWE 中,搜索“序列”可以是单个字符(如图所示),也可以是多标记序列(例如“is”),它同样会\thecharcount
提供2
。
通常,listofitems
用于解析输入列表中 [可能嵌套] 分隔符之间的字段。此处,如果我们使用所需的搜索字符串作为字段分隔符,则找到的搜索字符串(又称字段分隔符)的实例数将是所定位字段的数量(称为列表长度)减 1。
\documentclass{article}
\usepackage{listofitems}
\newcommand\countchars[2]{%
\setsepchar{#1}%
\readlist\mylist{#2}%
\edef\thecharcount{\the\numexpr\listlen\mylist[]-1\relax}%
\thecharcount
}
\begin{document}
\def\mydata{This is a test of the emergency broadcast system}
\countchars{e}{\mydata}
There are \thecharcount{} instances of the sequence ``e'' in ``\mydata''
\countchars{c}{\mydata}
There are \thecharcount{} instances of the sequence ``c'' in ``\mydata''
\end{document}
举一个如何使用和利用嵌套搜索的例子:
\documentclass{article}
\usepackage{listofitems}
\begin{document}
\def\mydata{This is a test of the emergency broadcast system}
\setsepchar{e/s}
\readlist\mylist{\mydata}
There are \the\numexpr\listlen\mylist[]-1\relax{} instances of the sequence
``\mylistsep[1]'' in ``\mydata''
\foreachitem\i\in\mylist{%
\def\tlev{\mylistsep[\icnt]}%
\def\blev{\mylistsep[\icnt,1]}%
There are \the\numexpr\listlen\mylist[\icnt]-1\relax{} instances of ``\blev'' between
\ifnum\icnt=1\relax the beginning \else \tlev$_{\the\numexpr\icnt-1\relax}$ \fi and
\ifnum\icnt=\listlen\mylist[]\relax the end\else e$_{\icnt}$\fi.\par
}
\end{document}