在自定义类中,我定义了一个自定义命令来排版电话号码,
\newcommand{\phone}[1]{\def\@phone{#1}}
\@phone
当我想用“变量”中的值替换时,我会在类中使用这个宏。但在某些情况下,我需要使用清理过的电话字符串。通常\phone
包含类似 的内容(623) 21-23-12-31
;但是,我想创建一个\phoneclean
只将数字输出为 的宏62321231231
。如何实现?
答案1
答案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}
直接执行 ,还可以先定义\zzz
via \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}