用于从其参数中删除所有非数字字符的宏

用于从其参数中删除所有非数字字符的宏

在自定义类中,我定义了一个自定义命令来排版电话号码,

\newcommand{\phone}[1]{\def\@phone{#1}}

\@phone当我想用“变量”中的值替换时,我会在类中使用这个宏。但在某些情况下,我需要使用清理过的电话字符串。通常\phone包含类似 的内容(623) 21-23-12-31;但是,我想创建一个\phoneclean只将数字输出为 的宏62321231231。如何实现?

答案1

在此处输入图片描述

您可以循环删除可删除的字符(此处空格会自动丢失)

\documentclass{article}

\def\foo#1{%
\ifx\relax#1\else
\ifx(#1\else\ifx)#1\else\ifx-#1\else#1\fi\fi\fi
\expandafter\foo
\fi}

\begin{document}

\foo(623) 21-23-12-31\relax

\end{document}

答案2

这是一个基于 LuaLaTeX 的解决方案,它利用 Lua 强大的string.gsub功能从宏的参数中清除所有非数字字符。

在此处输入图片描述

% !TEX TS-program = lualatex
\documentclass{article}

\usepackage{luacode} % for '\luaexec' macro
\newcommand\phoneclean[1]{\luaexec{% "%D" matches "any non-numeric character"
   tex.sprint (( string.gsub ( "#1" , "\%D" , "" ) )) }}

\begin{document}
\phoneclean{(623) 21-23-12-31}
\end{document}

附录:由于\luaexec是完全可扩展的,所以 也是完全可扩展的\phoneclean。因此,除了\phoneclean{(623) 21-23-12-31}直接执行 ,还可以先定义\zzzvia \newcommand{\zzz}{(623) 21-23-12-31},然后执行\phoneclean{\zzz}

答案3

您可以映射输入并保留数字。

\documentclass{article}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\getphonenumber}{m}
 {
  \lin_getphoneno:e { #1 }
 }

\cs_new:Nn \lin_getphoneno:n
 {
  \tl_map_function:nN { #1 } \__lin_getphoneno_check:n
 }
\cs_generate_variant:Nn \lin_getphoneno:n { e }

\cs_new:Nn \__lin_getphoneno_check:n
 {
  \str_case:nn { #1 }
   {
    {0}{0} {1}{1} {2}{2} {3}{3} {4}{4} {5}{5} {6}{6} {7}{7} {8}{8} {9}{9}
   }
 }

\ExplSyntaxOff

\begin{document}

\getphonenumber{(623) 21-23-12-31}

\edef\test{\getphonenumber{(623) 21-23-12-31}}
\texttt{\meaning\test}

\def\phoneno{(623) 21-23-12-31}

\getphonenumber{\phoneno}

\edef\test{\getphonenumber{\phoneno}}
\texttt{\meaning\test}

\end{document}

您会看到,\getphonenumber当数字存储在宏中时,它也有效。

在此处输入图片描述

答案4

以下使用低级标记循环并检查数字(只有类别 12 的数字应通过此过滤器并保留在输出中,特别是扩展为有效数字的宏也会被过滤)。它是完全可扩展的,精确地分两步扩展,并且结果不会在 内进一步扩展\edef。它假设\stop永远不会成为参数的一部分,并且参数不包含括号组。

*如果在输入中的第一个标记之后给出一个可选项,\sanitisephone则会扩展一次(允许单个宏作为输入)。

*需要使用一些技巧才能让 -variant\NewExpandableDocument仅通过两个步骤就能扩展(请注意,这种技巧可以被认为破坏了内核团队的编码风格指南)。

\documentclass{article}

\makeatletter
\providecommand\@secondofthree[3]{#2}
\providecommand\@gobblefour[4]{}

\newcommand\phonenumber{}
\newcommand\phone[1]{\edef\phonenumber{\unexpanded{#1}}}

\newcommand\filternondigit[1]
  {%
    \ifnum\@ne<1\noexpand#1
      \@firstoftwo
    \fi
    \@gobbletwo\unexpanded{#1}%
  }

\newcommand\sanitisephone
  {\unexpanded\expanded\sanitisephone@args}
\NewExpandableDocumentCommand\sanitisephone@args{s +m}
  {{{\IfBooleanT{#1}\expandafter\sanitisephone@#2\stop}}}
\newcommand\sanitisephone@[1]
  {\sanitisephone@ifstop#1\@gobblefour\stop\filternondigit{#1}\sanitisephone@}
\long\def\sanitisephone@ifstop#1\stop{}
\makeatother

\begin{document}
\phone{(623) 21-23-12-31}
\edef\mytmp{\sanitisephone*\phonenumber}\texttt{\meaning\mytmp}

\edef\mytmp{\sanitisephone{(623) 21-23-12-31}}\texttt{\meaning\mytmp}
\end{document}

相关内容