Split phone numbers into groups based on first digit

This can be done with the xstring package, which provides commands for extracting and comparing substrings.

It is possible to do some preprocessing to the string before the formatting is applied, for example to remove whitespace. The xstring commands for extracting substrings, modifications and counts have the general syntax \Command{arg1}{...}[\result] where the optional \result argument stores the result for further processing (if this argument is not given the result is just printed directly). This can be used for preprocessing to store the preprocessed string and do the rest of the processing on the result string.

MWE:

\documentclass{article}
\newif\ifstartnum
\usepackage{xstring}
\newcommand{\splitdigits}[1]{%
\StrDel{#1}{ }[\newstring]%
\StrLen{\newstring}[\mylen]%
\ifnum \mylen=8 %
\startnumfalse%
\IfBeginWith{\newstring}{4}{\startnumtrue}{}%
\IfBeginWith{\newstring}{8}{\startnumtrue}{}%
\IfBeginWith{\newstring}{9}{\startnumtrue}{}%
\ifstartnum%
\StrLeft{\newstring}{3}\ \StrMid{\newstring}{4}{5}\ \StrRight{\newstring}{3}%
\else%
\StrLeft{\newstring}{2}\ \StrMid{\newstring}{3}{4}\ \StrMid{\newstring}{5}{6}\ \StrRight{\newstring}{2}%
\fi%
\else%
#1%
\fi%
}
\begin{document}
\noindent\splitdigits{23276011}\\
\splitdigits{40443033}\\
\splitdigits{82043033}\\
\splitdigits{90964159}\\
\splitdigits{07979}\\
\splitdigits{110} \splitdigits{112} \splitdigits{113}\\
\splitdigits{9 09 6415 9}\\
\splitdigits{90 96 41 59}\\
\splitdigits{232 76 011}
\end{document}

Result:

enter image description here


Branch according to the length of the argument: if it is eight digit long, branch with respect to the first digit; otherwise print the argument.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\phone}{m}
 {
  \nebu_phone:n { #1 }
 }

\cs_new:Nn \nebu_phone:n
 {
  \int_compare:nTF { \tl_count:n { #1 } = 8 }
   {
    \__nebu_phone_eight:n { #1 }
   }
   {
    #1
   }
 }

\cs_new:Nn \__nebu_phone_eight:n
 {
  \str_case_e:nnF { \tl_head:n { #1 } }
   {
    {4}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
    {8}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
    {9}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
   }
   {
    \__nebu_phone_ii:nnnnnnnn #1
   }
 }

\cs_new:Nn \__nebu_phone_iii_ii_iii:nnnnnnnn { #1#2#3\nobreakspace#4#5\nobreakspace#6#7#8 }
\cs_new:Nn \__nebu_phone_ii:nnnnnnnn { #1#2\nobreakspace#3#4\nobreakspace#5#6\nobreakspace#7#8 }

\ExplSyntaxOff

\begin{document}

\phone{23276011}

\phone{40443033}

\phone{82043033}

\phone{90964159}

\phone{07979}

\phone{110}, \phone{112}, \phone{113}

\end{document}

enter image description here

If you want to remove spaces from the input, you have to give up expandability:

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\phone}{m}
 {
  \nebu_phone:n { #1 }
 }

\tl_new:N \l__nebu_phone_tl

\cs_new_protected:Nn \nebu_phone:n
 {
  \tl_set:Nn \l__nebu_phone_tl { #1 }
  \tl_remove_all:Nn \l__nebu_phone_tl { ~ }
  \int_compare:nTF { \tl_count:N \l__nebu_phone_tl = 8 }
   {
    \__nebu_phone_eight:V \l__nebu_phone_tl
   }
   {
    \tl_use:N \l__nebu_phone_tl
   }
 }

\cs_new:Nn \__nebu_phone_eight:n
 {
  \str_case_e:nnF { \tl_head:n { #1 } }
   {
    {4}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
    {8}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
    {9}{ \__nebu_phone_iii_ii_iii:nnnnnnnn #1 }
   }
   {
    \__nebu_phone_ii:nnnnnnnn #1
   }
 }
\cs_generate_variant:Nn \__nebu_phone_eight:n { V }

\cs_new:Nn \__nebu_phone_iii_ii_iii:nnnnnnnn { #1#2#3\nobreakspace#4#5\nobreakspace#6#7#8 }
\cs_new:Nn \__nebu_phone_ii:nnnnnnnn { #1#2\nobreakspace#3#4\nobreakspace#5#6\nobreakspace#7#8 }

\ExplSyntaxOff

\begin{document}

\phone{232 76 011}

\phone{40 44 30 33}

\phone{820 430 33}

\phone{90964159}

\phone{079 79}

\phone{110}, \phone{112}, \phone{113}

\end{document}

The output is the same.