通过替换和拆分来处理字符串

通过替换和拆分来处理字符串

我有一个输入字符串,如“123-45”或“1-3-5”或“2-4; 6-8”,其中的减号应该被删除。使用xstring包很容易做到这一点。

\StrSubstitute{#1}{-}{}

下一步是在分号处拆分输入字符串。这也许可以用来完成\StrMid。最终输出应该是:

123-45 = \somecommand{12345}
1-3-5 = \somecommand{135}
2-4 = \somecommand{24}
6-8 = \somecommand{68}

目前我有一个不实际工作的代码:

\newcommand{\test}[1]{%
  \newcommand{\stripped}{\StrSubstitute{#1}{-}{}}%
  \IfInteger{\stripped}{\somecommand{\stripped}}{error}%
}

我该如何解决这个问题?

答案1

您还可以使用该xstring包:

\documentclass[a4paper, 11pt]{article}

\usepackage{xstring}
\def\somecommand#1{\textbf{#1}\par}
\makeatletter
\newcommand{\test}[1]{%
  \StrSubstitute{#1}{-}{}[\stripped]%
  \StrCount{\stripped}{;}[\@tempcnta]
  \ifnum\@tempcnta=0
    %no semicolon
     \somecommand{\stripped}
  \else
   %semicolon
    \@test{\stripped}%
  \fi
}
\def\@test#1{%
\StrBefore{#1}{;}[\@tempa]
\StrBehind{#1}{;}[\@tempb]
\somecommand{\@tempa}
\test{\@tempb}
}
\begin{document}
\test{2-4; 6-8}

\test{123-45}
\end{document}

答案2

如果没有“实际使用”案例,那么除了提供一组在分号处拆分参数并删除连字符的宏之外,很难做更多的事情。

这是使用xparseLaTeX3 的一种方法;它假定参数中最多有一个分号:

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\somecommand}{>{\SplitArgument{1}{;}}m}
  { \somecommand_aux_i:nn #1 }
\cs_new:Nn \somecommand_aux_i:nn
  {
   \IfNoValueTF{#2}
     { \somecommand_aux_ii:nn {1}{#1} }
     { \somecommand_aux_ii:nn {1}{#1} \somecommand_aux_ii:nn {2}{#2} }
  }
\cs_new:Nn \somecommand_aux_ii:nn
  {
   \tl_set:Nn \l_tmpa_tl {#2}
   \tl_remove_all:Nn \l_tmpa_tl {-}
   \tl_remove_all:Nn \l_tmpa_tl {~}
   \somecommand_final:nx { #1 } { \l_tmpa_tl }
  }
\cs_new:Nn \somecommand_final:nx
  { Integer~#1~is~#2 \par }
\ExplSyntaxOff

现在输入

\somecommand{1-2}

\somecommand{1-2; 3-5}

\somecommand{1-3-5}

将产生


在此处输入图片描述


这只是一个适当定义的问题\somecommand_final:nn

一种不同的实现,使用逗号分隔列表(并避免xparse),假定参数中不出现逗号并允许任意数量的分号:

\usepackage{expl3}
\ExplSyntaxOn
\clist_new:N \somecommand_clist
\cs_new:Npn \somecommand #1
  {
   \int_set:Nn \l_tmpa_int {0}
   \tl_set:Nn \l_tmpa_tl {#1}
   \tl_remove_all:Nn \l_tmpa_tl {-}
   \tl_remove_all:Nn \l_tmpa_tl {~}
   \tl_replace_all:Nnn \l_tmpa_tl {;} {,}
   \clist_set:Nx \somecommand_clist { \l_tmpa_tl }
   \clist_map_function:NN \somecommand_clist \somecommand_mapping:n
  }
\cs_new:Nn \somecommand_mapping:n
  {
   \int_incr:N \l_tmpa_int
   \somecommand_final:nn { \int_to_arabic:n {\l_tmpa_int } } { #1 }
  }
\cs_new:Nn \somecommand_final:nn
  { Integer~#1~is~#2 \par}
\ExplSyntaxOff

请注意,\l_tmpa_int只是为了为各个分号分隔的部分提供索引。

解释

让我们看一下第二种实现方式以便理解这些步骤。

(1)我们分配一个“clist”变量(逗号分隔的列表)

\clist_new:N \somecommand_clist

(2)我们定义主命令,它有一个参数。

\cs_new:Npn \somecommand #1
  {
   \int_set:Nn \l_tmpa_int {0}
   \tl_set:Nn \l_tmpa_tl {#1}
   \tl_remove_all:Nn \l_tmpa_tl {-}
   \tl_remove_all:Nn \l_tmpa_tl {~}
   \tl_replace_all:Nnn \l_tmpa_tl {;} {,}
   \clist_set:Nx \somecommand_clist { \l_tmpa_tl }
   \clist_map_function:NN \somecommand_clist \somecommand_mapping:n
  }

它首先将暂存整数变量初始化\l_tmpa_int为零,并将暂存标记列表变量设置\l_tmpa_tl为参数。然后我们从其内容中删除所有连字符和所有空格(~这是 LaTeX3 在有效时表示空格的方式\ExplSyntaxOn);最后我们将所有分号改为逗号,并将标记列表转换为 clist(这实际上是多余的,但为了使用正确的数据类型,我们会表现得像个好孩子)。最后我们这样做\clist_map_function:NN。如果 clist 是

{a,b,c}

这相当于执行

\somecommand_mapping:n {a}
\somecommand_mapping:n {b}
\somecommand_mapping:n {c}

(3)我们必须为映射函数提供一个含义:

\cs_new:Nn \somecommand_mapping:n
  {
   \int_incr:N \l_tmpa_int
   \somecommand_final:nn { \int_to_arabic:n {\l_tmpa_int } } { #1 }
  }

只需增加临时整数变量并\somecommand_final:nn使用第一个参数执行可打印形式转换的整数和当前 clist 项。

(4)下面是最后一个命令,它使用参数执行一些操作

\cs_new:Nn \somecommand_final:nn
  { Integer~#1~is~#2 \par}

当然,每个人都有自由去做任何需要做的事情。

再试一次(按照 Joseph Wright 的建议)

这个也可以用于任意数量的分号;我们利用\SplitList修剪两边空格的事实;输入\somecommand{1-2; 3-4}如下#1形式{1-2}{3-4}

\ExplSyntaxOn
\NewDocumentCommand{\somecommand}{>{\SplitList{;}}m}
  {
   \int_set:Nn \l_tmpa_int {0}
   \tl_map_function:nN {#1} \somecommand_mapping:n
  }
\cs_new:Nn \somecommand_mapping:n
  {
   \int_incr:N \l_tmpa_int
   \tl_set:Nn \l_tmpa_tl {#1}
   \tl_remove_all:Nn \l_tmpa_tl {-}
   \somecommand_final:nn { \int_to_arabic:n {\l_tmpa_int} } { \l_tmpa_tl }
  }
\cs_new:Nn \somecommand_final:nn
  { Integer~#1~is~#2 \par }
\ExplSyntaxOff

答案3

一个老办法。这个办法来自 TeX in Practice。当我需要替换某些字符时,我会使用此方法。这是一个很长的代码,但宏可以与其他实用程序或工具一起存放在一个文件中。

\documentclass[a4paper, 11pt]{article}
 \makeatletter
 %<–––––––– code from TeX in Practice ––––––––>  
\newif\if@TestSubString
\def\SubStringConditional #1#2{%
    TT\fi
    \edef\@MainString{#1}%
    \edef\@SubStringConditionalTemp{{#1}{#2}}%
    \expandafter\@SubStringConditional\@SubStringConditionalTemp
}
\def\@SubStringConditional #1#2{% 
    \def\@TestSubS ##1#2##2\\{% 
        \def\@TestTemp{##1}% 
    }% 
    \@TestSubS #1#2\\
    \ifx\@MainString\@TestTemp
        \@TestSubStringfalse
    \else
        \@TestSubStringtrue
    \fi
    \if@TestSubString
}

\def\RecursionMacroEnd #1#2#3{% 
    #1\relax
        \def\@RecursionMacroEndNext{#2}% 
    \else
        \def\@RecursionMacroEndNext{#3}% 
    \fi
    \@RecursionMacroEndNext
}

\def\ReplaceSubStrings #1#2#3#4{%
    \def\@ReplaceResult{#1}%
    \edef\@ReplaceMain{#2}%
    \edef\@ReplaceSub{#3}%
    \edef\@ReplaceSubRep{#4}%
    \@ReplaceSubStrings
}
\def\@ReplaceSubStrings{% 
    \RecursionMacroEnd
        {\if\SubStringConditional{\@ReplaceMain}{\@ReplaceSub}}%
      {\@ReplaceSubStringsDo}{\expandafter\edef\@ReplaceResult{\@ReplaceMain}}%
}
\def\@ReplaceSubStringsDoX{%
    \def\@ReplaceSubStringsDoA ##1%
}%
\def\@ReplaceSubStringsDo{% 
    \expandafter\@ReplaceSubStringsDoX \@ReplaceSub
                                    ##2\@EndReplaceSubStrings{%
        \edef\@ReplaceMain{##1\@ReplaceSubRep ##2}%
    }%
    \expandafter\@ReplaceSubStringsDoA\@ReplaceMain
        \@EndReplaceSubStrings
    \@ReplaceSubStrings
}
\makeatother

\begin{document} 
\def\awordwithminus{1-3------6-5}
\ReplaceSubStrings{\awordwithoutminus}{\awordwithminus}{-}{}  
\awordwithoutminus
\end{document}

答案4

\documentclass{article}
\usepackage{catoptions}
\makeatletter
% #1 = token to parse
% #2 = string to remove
% #3 = replacement
% #4 = number of replacements
\new@def*\replacestrNtimes#1#2#3#4{%
  \expandafter\cptswap\expandafter{\expandafter{\romannumeral\number#4000}}%
  {\cpt@replacestrNtimes#1\@empty\@nnil{#2}{#3}}{}%
}
\new@def*\cpt@replacestrNtimes#1#2\@nnil#3#4#5#6{%
  \ifnullTF{#5}{#6#1#2}{%
    \ifstrcmpTF{#1}\@empty{#6}{%
      \ifstrcmpTF{#1}{#3}{%
        \expandafter\cptswap\expandafter{\expandafter{\@gobble#5}}%
        {\cpt@replacestrNtimes#2\@nnil{#3}{#4}}{#6#4}%
      }{%
        \cpt@replacestrNtimes#2\@nnil{#3}{#4}{#5}{#6#1}%
      }%
    }%
  }%
}
\makeatother

% Examples:
%\edef\x{\replacestrNtimes{x--y-z}{-}{+}{2}}
%\edef\x{\replacestrNtimes{x--y-z}{-}{+}{4}}
%\edef\x{\replacestrNtimes{x--y-z}{-}{+}{1}}
%\edef\x{\replacestrNtimes{x--y-z}{-}{+}{0}}
 \edef\x{\replacestrNtimes{x--y-z}{-}{}{2}}
\show\x

相关内容