使用 phonenumber-package 和宏作为参数来格式化电话号码(expand-problem)

使用 phonenumber-package 和宏作为参数来格式化电话号码(expand-problem)

我尝试使用phonenumbers-package 来格式化电话号码。作为参数,我想使用宏(在实际文档中,宏将用pgfkeys! 定义)

我到目前为止尝试过的:

\documentclass{article}

\usepackage[ngerman]{babel}
\usepackage[area-code-sep=hyphen, country=DE]{phonenumbers}

\begin{document}
\def\tel{01601234567}

\noindent
\phonenumber{01601234567}\\                                 % Correct!
\phonenumber{\tel}\\                                        % No Output
\expandafter\phonenumber{\tel}\\                            % No Output
\expandafter\phonenumber\tel\\                              % Unformatted
\expandafter\phonenumber\bgroup\tel\egroup\\                % Unformatted
\expandafter\phonenumber\expandafter\bgroup\tel\egroup\\    % Unformatted
\end{document}

我不明白如何\tel在使用 -macro 作为参数之前将其扩展。

提前致谢!

答案1

\expandafter\phonenumber\expandafter{\tel}

在示例中有效。您需要第一个\expandafter“跳过” \phonenumber,第二个\expandafter“跳过” {,因此\tel在之前对其进行了扩展\phonenumber{,最终得到\phonenumber{01601234567}

在示例中,\phonenumber传递实际数字而不是包含数字的宏非常重要。因此,在使用参数之前,我们必须先展开(解包)该参数(一次)。

\tel如果您在实际文档中使用不同的 定义,则可能需要更多\expandafter,如果事实证明该定义使用了更多“层”。如果您另外有\def\telA{\tel},一个\expandafter是不够的,您将需要在 的每一侧有三个\phonenumber,因为您现在需要扩展\telA两次才能达到该数字。对于三级扩展,您将需要七个。请参阅\expandafter 和 \aftergroup:2n+1 和 n^2-1 规则从何而来?

如果您确信只要继续扩展宏直到无法扩展为止,宏就会扩展为数字,则可以使用另一种方法,这种方法在\expandafters需要多个扩展步骤的情况下可以为您节省很多时间。只需完全扩展参数即可。您可以使用\edef\noexpand(请参阅何时使用 \edef、\noexpand 和 \expandafter?)或\romannumeral诀窍(https://www.texdev.net/2011/07/05/expansion-using-romannumeral/)。当你的宏由多个元素组成时,\edef和之间的区别就变得很重要,只会尽可能地扩展第一个标记,将扩展所有内容。\romannumeral\romannumeral\edef

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage[area-code-sep=hyphen, country=DE]{phonenumbers}

\def\tel{01601234567}
\def\telA{\tel}
\def\telB{\telA}

\def\telp{0160}
\def\telq{1234567}
\def\telpA{\telp\telq}
\def\telpB{\telpA}

\def\myphonenumber#1{\phonenumber{#1}\quad(\texttt{\detokenize{#1}})}

\begin{document}
\begin{enumerate}
\item
\myphonenumber{01601234567}

\item % does not work, \tel is not a number
\myphonenumber{\tel}

\item
\expandafter\myphonenumber\expandafter{\tel}

\item % does not work, \telA needs two expansion steps to get a number
\expandafter\myphonenumber\expandafter{\telA}

\item
\expandafter\expandafter\expandafter
\myphonenumber
\expandafter\expandafter\expandafter{\telA}

\item
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
\myphonenumber
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
{\telB}

\item
\begingroup
\edef\temp{\endgroup
  \noexpand\myphonenumber{\tel}}
\temp

\item
\begingroup
\edef\temp{\endgroup
  \noexpand\myphonenumber{\telA}}
\temp

\item
\begingroup
\edef\temp{\endgroup
  \noexpand\myphonenumber{\telB}}
\temp

\item 
\expandafter\myphonenumber\expandafter{\romannumeral-`0\tel}

\item
\expandafter\myphonenumber\expandafter{\romannumeral-`0\telA}

\item
\expandafter\myphonenumber\expandafter{\romannumeral-`0\telB}

\item
\begingroup
\edef\temp{\endgroup
  \noexpand\myphonenumber{\telpB}}
\temp

\item
\expandafter\myphonenumber\expandafter{\romannumeral-`0\telpB}
\end{enumerate}
\end{document}

{\bgroup}\egroup作为参数分隔符并不等效。这就是为什么无法\expandafter\phonenumber\expandafter\bgroup\tel\egroup正常工作。您可以看到\bgroup\egroup{}

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\def\foo#1{-\detokenize{#1}-}

\begin{document}
\foo{DEF}

\foo\bgroup ABC\egroup
\end{document}

第一行按预期工作并显示“-DEF-”,但第二行抛出有关太多}s 的错误并显示“- \bgroup-ABC”,这表明\foo假设\bgroup是它的参数而不是整个字符串ABC

答案2

我是这样定义的\phonenumber

\documentclass{article}

\usepackage[ngerman]{babel}
\usepackage[area-code-sep=hyphen, country=DE]{phonenumbers}

\newcommand\tel{01601234567}

\ExplSyntaxOn

\RenewDocumentCommand \phonenumber {O{}mo}
 {
  \group_begin:
  \keys_set:nn {phonenumbers} {#1}
  \IfNoValueTF { #3 }
   { \phone_nummer_ueberpruefen:f { #2 } }
   { \phone_nummer_ueberpruefen:ff { #2 } { #3 } }
  \phone_nummer_ausgeben:
  \group_end:
 }

\cs_new_protected:Nn \phone_nummer_ueberpruefen:nn
 {
  \phone_durchwahl_ueberpruefen:n {#2}
  \phone_nummer_ueberpruefen:n {#1}
  \bool_lazy_or:nnF
   {\str_if_eq_p:Vn \l_phone_land_str {DE}}
   {\str_if_eq_p:Vn \l_phone_land_str {AT}}
   {
    \bool_if:NF \l_phone_durchwahl_leer_bool
     {
      \msg_warning:nn {phonenumbers} {illegal~extension}
     }
   }
 }
\cs_generate_variant:Nn \phone_nummer_ueberpruefen:n {f}
\cs_generate_variant:Nn \phone_nummer_ueberpruefen:nn {ff}

\ExplSyntaxOff

\begin{document}

\phonenumber{01601234567}

\phonenumber{\tel}

\end{document}

我首先将包中的大定义拆分开来,使用\NewDocumentCommand来仅整理可选参数并调用内部函数。这里需要使用\RenewDocumentCommand

这样,需要的布尔检查更少,灵活性也更好;例如,只需更改\phone_nummer_ueberpruefen:n\phone_nummer_ueberpruefen:f允许将输入指定为\phonenumber宏。

\documentclass{article}

\usepackage[ngerman]{babel}
\usepackage[area-code-sep=hyphen, country=DE]{phonenumbers}

\newcommand\tel{01601234567}

\ExplSyntaxOn

\RenewDocumentCommand \phonenumber {O{}mo}
 {
  \group_begin:
  \keys_set:nn {phonenumbers} {#1}
  \IfNoValueTF { #3 }
   { \phone_nummer_ueberpruefen:f { #2 } }
   { \phone_nummer_ueberpruefen:nn { #2 } { #3 } }
  \phone_nummer_ausgeben:
  \group_end:
 }

\cs_new_protected:Nn \phone_nummer_ueberpruefen:nn
 {
  \phone_durchwahl_ueberpruefen:n {#2}
  \phone_nummer_ueberpruefen:f {#1} % <--- change :n to :f
  \bool_lazy_or:nnF
   {\str_if_eq_p:Vn \l_phone_land_str {DE}}
   {\str_if_eq_p:Vn \l_phone_land_str {AT}}
   {
    \bool_if:NF \l_phone_durchwahl_leer_bool
     {
      \msg_warning:nn {phonenumbers} {illegal~extension}
     }
   }
 }
\cs_generate_variant:Nn \phone_nummer_ueberpruefen:n {f}

\ExplSyntaxOff

\begin{document}

\phonenumber{01601234567}

\phonenumber{\tel}

\end{document}

在此处输入图片描述

相关内容