【问题标题】:australian mobile numbers strings formatting澳大利亚手机号码字符串格式
【发布时间】:2009-12-04 12:42:56
【问题描述】:

我需要格式化手机号码。 例如

+61421 123 123
0421 123 123
0061421123123
0421 123123

1) 转化成这种类型的字符串保存在dbf中

0421123123 

2) 然后以这种格式显示

0421 123 123

关于格式化数字的最有效方法有什么建议吗?

【问题讨论】:

  • 您所在国家/地区的所有手机号码都是以 04 开头还是巧合?
  • 你是说你只需要删除数字组之间的空格吗?
  • 澄清一下:在荷兰,所有手机号码都以 06 开头,所以在这种情况下,您首先要查找 6 或 4。在其他国家/地区,手机号码可以以任意号码组合开头,这种情况下,您必须从头数到最后以 10 个号码结束(嗯,这里是必填号码,不知道您所在的地区)和然后找出第一个数字是否是国家代码的一部分。
  • 是的,所有的数字都以 04 开头...这将是一个检查条件。但有些可能会输入国际前缀,我想删除并用前导 0 替换。所有数字都是 10 位长
  • 我认为问题的标题可以更具体一些。

标签: php regex parsing


【解决方案1】:
  • 从输入字符串中删除非数字
  • 分割最后 9 位数字
  • 添加零并存储

显示:

  • 在适当的地方插入空格

或者您可以将已经格式化的字符串存储到数据库中。

编辑(在评论中回答问题)。这似乎做得很好:

$s = '421123123';
$formatted = '0'.chunk_split($s, 3, ' ');

【讨论】:

  • 你知道有什么功能可以一次性在适当的地方插入空格吗?我在考虑 chunk_split() 但我必须在每个数字上运行两次......
  • 这不会检查数字是否确实符合规则(领先的国家前缀 (61) 或 0,然后是 9 位数字)。至少从 cmets 来看,规则似乎是这样的。最初的问题相当模糊......
  • @Tim:我不认为有可能保护自己免受所有可能的用户特质的影响。
  • 还有其他的格式化字符串的方法吗?数据库中的数字需要以0作为第一个数字来存储。
  • @ondrobaco: 只是substr 主题
【解决方案2】:

以下是澳大利亚手机号码的一些有效格式:

  • 0401 123 234
  • 041 123 3456
  • 0412 23 23 34(罕见)

所有这些都包含以 04 开头的 10 位数字,因此您可以删除空格并检查所有数字、起始数字和长度,但它更符合国际格式的电话号码。这增加了这些情况:

  • 61 411 234 345
  • +61 411 234 345
  • +61 (0)411 234 345

您可以在前面添加 00,但只能在某些使用 00 作为国际拨号前缀的国家/地区使用。我相信英国就是其中之一。所以棘手的部分是:

  • 国家代码是可选的
  • 国家/地区代码可能以 + 为前缀
  • 如果存在国家/地区代码,则前导 0 可能会被删除或替换为 (0)
  • 可以使用国际拨号前缀
  • 数字组的间距不一致
  • 在极少数情况下,可以使用连字符代替空格

我的建议L

  1. 如果有,则去掉前导 00;
  2. 如果有,则去掉前导 +;
  3. 去除前导 61(如果存在);
  4. 将前导 (0) 替换为 0;
  5. 如果还没有前导 0,则添加前导 0。
  6. 删除所有连字符和空格。

如果您没有以 04 开头的 10 位数字,请拒绝它。否则将其格式化为以下两种格式之一:

  • 国内:0412 345 789
  • 国际:+61 (0)412 345 789

【讨论】:

    【解决方案3】:

    这是一个 PHP 函数,它可以正确格式化电话号码,因此第一个空格在区号之后,其余的被平均分成两部分。这里的代码是针对芬兰区号的(不考虑国家代码),但可以根据需要进行修改:

    // Formats 0451234567 => 045 1234 567
    function format_phone($phone) {
        // List your area codes here
        $phone = preg_replace('/(02|03|05|06|08|09|013|014|015|016|017|018|019|020|040|041|042|043|044|045|046|050)/', '$1 ', $phone);
        list($d, $p) = explode(' ', $phone);
        $split_point = ceil(strlen($p) / 2);
        $p = substr($p, 0, $split_point).' '.substr($p, $split_point);
        return $d.' '.$p;
    }
    

    对于保存到数据库部分,只需剥离非数字字符,substr 到特定长度并插入到数据库中。如果您所在国家/地区的电话号码格式都相似且长度为 9 位(不带前缀 0),您可以使用以下方法从电话号码中取出最后 9 位:

    $phone = substr($phone, strlen($phone) - 9):
    

    并在前面加0。因此,这有效地将国家代码变为 0,但仅在所有电话号码长度相同时才有效。

    【讨论】:

      【解决方案4】:

      有很多更有效的方法可以做到这一点,并且以下代码的内存使用并不完美(修改传入参数),但是如果您想在不使用正则表达式的情况下遵循逻辑,这将起作用(注意不处理 13 或 1800 个数字,但如果您也需要这些数字,这很容易解决):

        function fmtAusPhoneNum($phoneNum) {
          // First strip spaces and non numerics
          $phoneNum = preg_replace('/\D+/', '', $phoneNum);
          // Strip AUS international access code
          if (substr($phoneNum, 0, 4) == '0011') {
              $phoneNum = substr($phoneNum, 4, strlen($phoneNum) - 4);
          }
          // Strip UK (and some others) international code
          if (substr($phoneNum, 0, 2) == '00') {
              $phoneNum = substr($phoneNum, 2, strlen($phoneNum) - 2);
          }
          // Add any other international prefixes here.
      
          // If first 2 digits are '61' then international format, take off 2
          if (substr($phoneNum, 0, 2) == '61') {
              $phoneNum = substr($phoneNum, 2, strlen($phoneNum) - 2);
          }
          // If STD 0 code, take it off.
          elseif (substr($phoneNum, 0, 1) == '0') {
              $phoneNum = substr($phoneNum, 1, strlen($phoneNum) - 1);
          }
          // Now should have a 9 char long digit.
          if (strlen($phoneNum)!=9) {
              echo "Warning: can't parse Australian number - less access codes, should have 9 digits only\n";
          }
          // If first digit is 4, it's a mobile, format 04xx xxx xxx
          if (substr($phoneNum, 0, 1) == '4') {
              $phoneNum = '0' . substr($phoneNum, 0, 3) . ' ' . substr($phoneNum, 3, 3) . ' ' . substr($phoneNum, 6, 3);
          } else {
              // It's a landline number, split into area code eg 03 and 2 lots of 4 digits
              $phoneNum = '0' . substr($phoneNum, 0, 1) . ' ' . substr($phoneNum, 1, 4) . ' ' . substr($phoneNum, 5, 4);
          }
          return $phoneNum;
      }
      
      // Test it
      echo fmtAusPhoneNum('0061 421 123 123') . "\n";
      echo fmtAusPhoneNum('0421741940') . "\n";
      echo fmtAusPhoneNum('+61421741940') . "\n";
      echo fmtAusPhoneNum('61394190231') . "\n";
      echo fmtAusPhoneNum('03 5521 7475') . "\n";
      

      【讨论】:

        【解决方案5】:

        这不太适合正则表达式。如何(a)删除非数字,(b)如果不是 10 个字符,则拒绝,(c)使用子字符串格式化。

        【讨论】:

        • Ewan 好点子,有时调试正则表达式所涉及的工作会使它们的使用时间变得低效,除非你是它们的专家。我在上面放了一些不使用它们的代码来看看它有多简单。除 13 xx xx 和紧急/目录辅助以外的所有澳大利亚号码均为 10 位数字(带零),或 9 位不带。
        【解决方案6】:
        ^(?:\+61|0061|0)(\d{3})\s*(\d{3})\s*(\d{3})$
        

        此正则表达式将匹配任何示例,在第 1 号反向引用中捕获 421,在第 1 号中捕获 123。 2,和123 在没有。 3.

        因此,如果您使用0\1\2\3 作为替换字符串,您将获得0421123123,如果您使用0\1 \2 \3,您将获得0421 123 123

        【讨论】:

        • 它并不适用于所有数字...我仅以这个特定数字为例。
        • 它确实适用于所有数字,除了只允许前缀 +61、0061 或 0(其余正好有 9 个数字)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-12-12
        • 2015-06-04
        • 1970-01-01
        • 2015-07-13
        • 2012-08-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多