【问题标题】:Using Number::Phone to validate and format使用 Number::Phone 进行验证和格式化
【发布时间】:2017-12-08 03:22:22
【问题描述】:

我正在尝试使用 Number::Phone from CPAN 来完成 2 个任务:

  1. 验证电话号码;和
  2. 以 E.164 表示法格式化数字。

但是,我无法弄清楚它是如何工作的。我的示例代码是:

#!/usr/bin/perl -w
use strict;
use warnings;
use Number::Phone;

foreach my $fnum ( '17888888', '97338888888', '00923455555333', '+97366767777' , '38383838') {
    my $phone = Number::Phone->new($fnum);
    my $norm = "";
    eval {
        $norm = $phone->format_using('E123'); # or 'Raw'
        print "E164 => '$norm'\n";
    } or do {
        print STDERR "Unable to parse '$fnum'\n";
    }
}

预期输出:

E164 => '+97317888888'
E164 => '+97338888888'
E164 => '+923455555333'
E164 => '+97366767777'
E164 => '+97338383838'

但结果不正确。我尝试使用Number::Phone::Normalize,但仍然没有成功:

#!/usr/bin/perl -w
use strict;
use warnings;
use Number::Phone::Normalize;

my %params = ( 
    'CountryCode'=>'973',
    'IntlPrefix' =>'00',
    'CountryCodeOut'=>'973',
    'IntlPrefixOut' => '+',
    );
my $nlz = Number::Phone::Normalize->new( %params );

foreach my $number ('17888888', '97338888888', '00923455555333', '+97366767777' , '38383838') {
    my $e164 = $nlz->intl( $number );
    print "E164 => '$e164'\n";
}

具有相同的预期输出:

E164 => '+97317888888'
E164 => '+97338888888'
E164 => '+923455555333'
E164 => '+97366767777'
E164 => '+97338383838'

但是,这也产生了错误的结果。下面的 sn-p Java 代码完美运行,这正是我试图在 Perl 中实现的。

// Uses libphonenumber: http://code.google.com/p/libphonenumber/
// setenv CLASSPATH .:libphonenumber-8.5.2.jar

// libphonenumber
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat;

public class ValidateList {
    public static void main(String[] args) {
        try {
            if (args.length != 1) {
                throw new IllegalArgumentException("Invalid number of arguments.");
            }

            String file = args[0];
            PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();

            try (java.io.BufferedReader br = new java.io.BufferedReader(new java.io.FileReader(file))) {
                String line = null;
                while ((line = br.readLine()) != null) {

                    try {
                        PhoneNumber phoneNumber = phoneUtil.parse(line, "BH");
                        boolean isValid = phoneUtil.isValidNumber(phoneNumber);
                        if (isValid) {
                            System.out.println( "E164 => " + phoneUtil.format(phoneNumber, PhoneNumberFormat.E164) );
                        }
                        else {
                            System.err.println( "Invalid => " + line);
                        }
                    } 
                    catch (NumberParseException e) {
                        System.err.println("NumberParseException for ("+line+"): " + e.toString());
                    }

                }
            }

        }
        catch (Exception e) {
            System.err.println(e);
            System.err.println("Usage: java ValidateList <fileNameWithPhoneNumbers>");
        }
    }
}
% cat input.txt
17888888
97338888888
00923455555333
+97366767777
38383838

% javac -cp libphonenumber-8.5.2.jar ValidateList.java

% java -cp .:libphonenumber-8.5.2.jar ValidateList input.txt 
E164 => +97317888888
E164 => +97338888888
E164 => +923455555333
E164 => +97366767777
E164 => +97338383838

非常感谢您的意见。

【问题讨论】:

  • 你认为什么是正确的?请提供您的预期输出和当前输出。这里的 Perl 人可能不知道如何运行您的 Java 源代码,它甚至不是 minimal reproducible example 并且不包含任何数字。
  • 谢谢@simbabque 我已经编辑了我的帖子以使其更全面。
  • Java 人员无法回答您的问题,因为它是关于 Perl 的。如果问题不是 about java,请不要用“java”标记它 - 这是一个不相关的标记。
  • 谢谢@ErwinBolwidt java 标签已被删除。

标签: perl unix perl-module libphonenumber


【解决方案1】:

当我为数字运行第一个示例代码时,其中两个无法解析:

17888888 - 这很明显,当拨打没有国家代码的 Number::Phone 时,由于不清楚这是来自哪个国家/地区,因此不会对其进行解析

00923455555333 - 923 是,根据谷歌快速搜索,巴基斯坦的国家代码。巴基斯坦拨号代码的维基百科页面显示没有 455,这让我认为这不是 Number::Phone 或 Wikipedia 的已知区号。我怀疑这是一个无效号码。

所以对于第一个数字:指定它应该来自哪个国家。

如果您确定其他号码是正确的,那么您比目前 Number::Phone 的开发者了解的更多,我相信他会很乐意以更完整的 Number 形式收到您的意见: :手机本地化包。

您的 Java 代码接受(可能)无效数字这一事实并不一定意味着它更正确,只是它在声明为正确数字时不那么挑剔。

编辑:

询问 Phone::Number 以解析输入“+923455555333”而不是“00923455555333”会导致所需的输出。

查看Phone::Number的来源:

# ... processing input arguments
$number = "+$number" unless($number =~ /^\+/);

很明显,00 被解释为“+00”,然后作为无效数字被拒绝。 View some discussion on that here

在我看来,您必须自己处理这个问题。 一种方法可能是简单地将前导 00 替换为 '+' - 最好仅在解析失败时。

另外一个号码,如果你说清楚它应该属于哪个国家,就可以解析出来。

大概是这样的:

my $phone = Number::Phone->new($fnum);
unless ($phone){
    $phone = Number::Phone->new('BH',$fnum);
    if ( !$phone && $fnum =~ s/^00/+/ ){
        # You should probably check the discussion I linked.
        # There may well be problems with this approach!
        $phone = Number::Phone->new($fnum);
    }
}

【讨论】:

  • 感谢@bytepusher 的回复。两个号码都有效。我应该使用“默认国家/地区”,但我还没有弄清楚如何在 Number::Phone 中执行此操作。请参阅(libphonenumber JavaScript 演示)https://rawgit.com/googlei18n/libphonenumber/master/javascript/i18n/phonenumbers/demo-compiled.html。对于“默认国家/地区”,请使用 BH。我提供的所有数字都应该是有效的,并且我希望它们采用 E.164 格式,如我的预期输出所示。
  • 我不确定这个“默认国家/地区”来自哪里 - 我没有在文档中看到它。
  • 在发现实际问题之后,我提出了一个建议,您可以如何解决这个问题。祝你好运!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-19
  • 2018-09-18
  • 1970-01-01
相关资源
最近更新 更多