Pertanyaan Regex komprehensif untuk validasi nomor telepon


Saya mencoba menyusun regex komprehensif untuk memvalidasi nomor telepon. Idealnya itu akan menangani format internasional, tetapi harus menangani format AS, termasuk yang berikut:

  • 1-234-567-8901
  • 1-234-567-8901 x1234
  • 1-234-567-8901 ext1234
  • 1 (234) 567-8901
  • 1,234.567.8901
  • 1/234/567/8901
  • 12345678901

Saya akan menjawab dengan usaha saya saat ini, tetapi saya berharap seseorang memiliki sesuatu yang lebih baik dan / atau lebih elegan.


824


asal


Jawaban:


Pilihan yang lebih baik ... cukup hapus semua karakter non-digit pada input (kecuali 'x' dan tanda '+'), berhati-hati karena kecenderungan Inggris untuk menulis angka dalam bentuk non-standar +44 (0) ... ketika diminta untuk menggunakan awalan internasional (dalam kasus khusus itu, Anda harus membuangnya (0) sepenuhnya).

Kemudian, Anda mendapatkan nilai seperti:

 12345678901
 12345678901x1234
 345678901x1234
 12344678901
 12345678901
 12345678901
 12345678901
 +4112345678
 +441234567890

Kemudian ketika Anda menampilkan, memformat ulang isi hati Anda. misalnya

  1 (234) 567-8901
  1 (234) 567-8901 x1234

482



Ternyata ada sesuatu yang spesifik untuk ini, setidaknya untuk Amerika Utara, yang disebut NANP.

Anda perlu menentukan apa yang Anda inginkan. Apa itu pembatas legal? Spasi, tanda hubung, dan titik? Tidak ada pemisah yang diizinkan? Dapatkah seseorang mencampur pembatas (mis., + 0,111-222,3333)? Bagaimana ekstensi (mis., 111-222-3333 x 44444) akan ditangani? Bagaimana dengan nomor khusus, seperti 911? Apakah kode area akan menjadi opsional atau diperlukan?

Berikut adalah regex untuk angka 7 atau 10 digit, dengan ekstensi yang diizinkan, pembatas adalah spasi, tanda hubung, atau titik:

^(?:(?:\+?1\s*(?:[.-]\s*)?)?(?:\(\s*([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9])\s*\)|([2-9]1[02-9]|[2-9][02-8]1|[2-9][02-8][02-9]))\s*(?:[.-]\s*)?)?([2-9]1[02-9]|[2-9][02-9]1|[2-9][02-9]{2})\s*(?:[.-]\s*)?([0-9]{4})(?:\s*(?:#|x\.?|ext\.?|extension)\s*(\d+))?$

277



.*

Jika pengguna ingin memberi Anda nomor teleponnya, percaya padanya untuk melakukannya dengan benar. Jika dia tidak ingin memberikannya kepada Anda maka memaksanya untuk memasukkan nomor yang valid akan mengirimnya ke situs pesaing atau membuatnya memasukkan string acak yang cocok dengan regex Anda. Saya bahkan mungkin tergoda untuk mencari nomor garis seks tingkat premium dan memasukkannya sebagai gantinya.

Saya juga akan mempertimbangkan hal-hal berikut sebagai entri yang valid di situs web:

"123 456 7890 until 6pm, then 098 765 4321"  
"123 456 7890 or try my mobile on 098 765 4321"  
"ex-directory - mind your own business"

274



Saya juga menyarankan melihat "libphonenumber"Perpustakaan Google. Saya tahu itu bukan regex, tetapi itu memang persis seperti yang Anda inginkan.

Misalnya, ia akan mengenali bahwa:

15555555555

adalah angka yang mungkin tetapi bukan angka yang valid. Ini juga mendukung negara-negara di luar AS.

Sorotan fungsi:

  • Mem-parsing / memformat / memvalidasi nomor telepon untuk semua negara / wilayah di dunia.
  • getNumberType - mendapat jenis nomor berdasarkan nomor itu sendiri; mampu membedakan Fixed-line, Mobile, Bebas Pulsa, Tarif Premium, Biaya Bersama, VoIP, dan Nomor Pribadi (kapan pun memungkinkan).
  • isNumberMatch - mendapat tingkat keyakinan apakah dua angka bisa sama.
  • getExampleNumber/getExampleNumberByType - memberikan nomor contoh yang valid untuk semua negara / wilayah, dengan opsi untuk menentukan jenis nomor telepon contoh yang diperlukan.
  • isPossibleNumber - cepat menebak apakah suatu bilangan adalah phonenumber yang mungkin dengan hanya menggunakan informasi panjang, jauh lebih cepat daripada validasi penuh.
  • isValidNumber - validasi penuh nomor telepon untuk suatu wilayah menggunakan informasi panjang dan awalan.
  • AsYouTypeFormatter- memformat nomor telepon on-the-fly ketika pengguna memasukkan setiap digit.
  • findNumbers - menemukan angka dalam input teks.
  • PhoneNumberOfflineGeocoder - memberikan informasi geografis terkait dengan nomor telepon.

Contoh

Masalah terbesar dengan validasi nomor telepon sangat tergantung secara kultural.

  • Amerika
    • (408) 974–2042 adalah sah Nomor AS
    • (999) 974–2042 aku s bukan yang valid Nomor AS
  • Australia
    • 0404 999 999 adalah sah Nomor Australia
    • (02) 9999 9999 juga merupakan sah Nomor Australia
    • (09) 9999 9999 aku s bukan yang valid Nomor Australia

Ekspresi reguler baik-baik saja untuk memeriksa format nomor telepon, tetapi itu tidak benar-benar akan dapat memeriksa keabsahan dari nomor telepon.

Saya menyarankan untuk melewatkan ekspresi reguler sederhana untuk menguji nomor telepon Anda, dan menggunakan pustaka seperti Google libphonenumber (tautan ke proyek GitHub).

Memperkenalkan libphonenumber!

Menggunakan salah satu contoh Anda yang lebih rumit, 1-234-567-8901 x1234, Anda mendapatkan data berikut keluar libphonenumber (tautan ke demo online):

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     true

Formatting Results:

E164 format                    +12345678901
Original format                (234) 567-8901 ext. 123
National format                (234) 567-8901 ext. 123
International format           +1 234-567-8901 ext. 123
Out-of-country format from US  1 (234) 567-8901 ext. 123
Out-of-country format from CH  00 1 234-567-8901 ext. 123

Jadi Anda tidak hanya belajar jika nomor telepon valid (yang mana), tetapi Anda juga mendapatkan pemformatan nomor telepon yang konsisten di lokal Anda.

Sebagai bonus, libphonenumber memiliki sejumlah dataset untuk memeriksa validitas nomor telepon, juga, jadi periksa nomor seperti +61299999999 (versi internasional dari (02) 9999 9999) mengembalikan sebagai nomor yang valid dengan pemformatan:

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     true

Formatting Results

E164 format                    +61299999999
Original format                61 2 9999 9999
National format                (02) 9999 9999
International format           +61 2 9999 9999
Out-of-country format from US  011 61 2 9999 9999
Out-of-country format from CH  00 61 2 9999 9999

libphonenumber juga memberi Anda banyak manfaat tambahan, seperti mengambil lokasi tempat nomor telepon terdeteksi, dan juga mendapatkan informasi zona waktu dari nomor telepon:

PhoneNumberOfflineGeocoder Results
Location        Australia

PhoneNumberToTimeZonesMapper Results
Time zone(s)    [Australia/Sydney]

Tetapi nomor telepon Australia yang tidak valid ((09) 9999 9999) mengembalikan bahwa itu bukan nomor telepon yang valid.

Validation Results

Result from isPossibleNumber()  true
Result from isValidNumber()     false

Versi Google memiliki kode untuk Java dan Javascript, tetapi orang juga telah mengimplementasikan perpustakaan untuk bahasa lain yang menggunakan dataset nomor telepon Google i18n:

Kecuali Anda yakin bahwa Anda akan selalu menerima nomor dari satu lokal, dan mereka selalu akan berada dalam satu format, saya akan sangat menyarankan untuk tidak menulis kode Anda sendiri untuk ini, dan menggunakan libphonenumber untuk memvalidasi dan menampilkan nomor telepon.


128



/^(?:(?:\(?(?:00|\+)([1-4]\d\d|[1-9]\d?)\)?)?[\-\.\ \\\/]?)?((?:\(?\d{1,}\)?[\-\.\ \\\/]?){0,})(?:[\-\.\ \\\/]?(?:#|ext\.?|extension|x)[\-\.\ \\\/]?(\d+))?$/i

Ini cocok:

 - (+351) 282 43 50 50
 - 90191919908
 - 555-8909
 - 001 6867684
 - 001 6867684x1
 - 1 (234) 567-8901
 - 1-234-567-8901 x1234
 - 1-234-567-8901 ext1234
 - 1-234 567.89/01 ext.1234
 - 1(234)5678901x1234
 - (123)8575973
 - (0055)(123)8575973

Pada $ n, itu menghemat:

  1. Indikator negara
  2. Nomor telepon
  3. Perpanjangan

Anda bisa mengujinya https://www.regexpal.com/?fam=99127


65



Meskipun jawaban untuk menghapus semua spasi putih itu rapi, itu tidak benar-benar memecahkan masalah yang diajukan, yaitu menemukan regex. Ambil, misalnya, skrip pengujian saya yang mengunduh halaman web dan ekstrak semua nomor telepon menggunakan regex. Karena Anda akan membutuhkan regex, Anda mungkin juga memiliki regex yang melakukan semua pekerjaan. Saya datang dengan ini:

1?\W*([2-9][0-8][0-9])\W*([2-9][0-9]{2})\W*([0-9]{4})(\se?x?t?(\d*))?

Berikut skrip perl untuk mengujinya. Saat Anda cocok, $ 1 berisi kode area, $ 2 dan $ 3 berisi nomor telepon, dan $ 5 berisi ekstensi. Script pengujian saya mengunduh file dari internet dan mencetak semua nomor telepon di dalamnya.

#!/usr/bin/perl

my $us_phone_regex =
        '1?\W*([2-9][0-8][0-9])\W*([2-9][0-9]{2})\W*([0-9]{4})(\se?x?t?(\d*))?';


my @tests =
(
"1-234-567-8901",
"1-234-567-8901 x1234",
"1-234-567-8901 ext1234",
"1 (234) 567-8901",
"1.234.567.8901",
"1/234/567/8901",
"12345678901",
"not a phone number"
);

foreach my $num (@tests)
{
        if( $num =~ m/$us_phone_regex/ )
        {
                print "match [$1-$2-$3]\n" if not defined $4;
                print "match [$1-$2-$3 $5]\n" if defined $4;
        }
        else
        {
                print "no match [$num]\n";
        }
}

#
# Extract all phone numbers from an arbitrary file.
#
my $external_filename =
        'http://web.textfiles.com/ezines/PHREAKSANDGEEKS/PnG-spring05.txt';
my @external_file = `curl $external_filename`;
foreach my $line (@external_file)
{
        if( $line =~ m/$us_phone_regex/ )
        {
                print "match $1 $2 $3\n";
        }
}

Edit:

Anda dapat mengubah \ W * menjadi \ s * \ W \ \ * dalam regex untuk mengencangkannya sedikit. Saya tidak memikirkan regex dalam hal, katakanlah, memvalidasi input pengguna pada formulir ketika saya menulisnya, tetapi perubahan ini memungkinkan untuk menggunakan regex untuk tujuan itu.

'1?\s*\W?\s*([2-9][0-8][0-9])\s*\W?\s*([2-9][0-9]{2})\s*\W?\s*([0-9]{4})(\se?x?t?(\d*))?';

62



Saya menjawab pertanyaan ini pada pertanyaan SO yang lain sebelum memutuskan untuk memasukkan jawaban saya sebagai jawaban di utas ini, karena tidak ada yang membahas cara meminta / tidak memerlukan item, hanya membagi-bagikan regex: Regex bekerja salah, mencocokkan hal tak terduga

Dari posting saya di situs itu, saya telah membuat panduan cepat untuk membantu siapa saja dengan membuat regex mereka sendiri untuk format nomor telepon yang diinginkan, yang saya akan peringatan (seperti yang saya lakukan di situs lain) bahwa jika Anda terlalu membatasi, Anda mungkin tidak mendapatkan hasil yang diinginkan, dan tidak ada solusi "satu ukuran cocok untuk semua" untuk menerima semua nomor telepon yang mungkin di dunia - hanya apa yang Anda putuskan untuk terima sebagai format pilihan Anda. Gunakan dengan resiko Anda sendiri.

Lembar contekan cepat

  • Mulai ungkapan: /^ 
  • Jika Anda ingin membutuhkan ruang, gunakan: [\s] atau \s 
  • Jika Anda ingin mewajibkan tanda kurung, gunakan: [(] dan [)] . Menggunakan \( dan \) itu jelek dan bisa membuat hal-hal membingungkan.
  • Jika Anda ingin sesuatu menjadi opsional, masukkan a ? setelah itu
  • Jika Anda ingin tanda hubung, ketik saja - atau [-] . Jika Anda tidak memasukkannya dulu atau terakhir dalam serangkaian karakter lain, Anda mungkin perlu menghindarinya: \-
  • Jika Anda ingin menerima pilihan berbeda di slot, letakkan tanda kurung di sekitar opsi: [-.\s] akan membutuhkan tanda hubung, titik, atau spasi. Tanda tanya setelah braket terakhir akan membuat semua itu opsional untuk slot itu.
  • \d{3} : Membutuhkan nomor 3-digit: 000-999. Singkatan untuk [0-9][0-9][0-9].
  • [2-9] : Membutuhkan digit 2-9 untuk slot itu.
  • (\+|1\s)? : Terima "plus" atau 1 dan spasi (karakter pipa, |, adalah "atau"), dan menjadikannya opsional. Tanda "plus" harus diloloskan.
  • Jika Anda ingin nomor tertentu untuk dicocokkan dengan slot, masukkan mereka: [246] akan membutuhkan 2, 4, atau 6. [77|78] akan membutuhkan 77 atau 78.
  • $/ : Akhiri ungkapan

38



Saya menulis paling sederhana (meskipun saya tidak perlu titik di dalamnya).

^ ([0-9 \ (\) \ / \ + \ -] *) $

Seperti yang disebutkan di bawah ini, ia hanya memeriksa karakter, bukan struktur / urutannya


27



Perhatikan bahwa pengupasan () karakter tidak berfungsi untuk gaya penulisan nomor UK yang umum: +44 (0) 1234 567890 yang berarti menghubungi nomor internasional:
+441234567890
atau di dial Inggris 01234567890


22



Jika Anda hanya ingin memverifikasi bahwa Anda tidak memiliki sampah acak di lapangan (yaitu, dari spammer formulir), regex ini harus dilakukan dengan baik:

^[0-9+\(\)#\.\s\/ext-]+$

Perhatikan bahwa itu tidak memiliki aturan khusus untuk berapa banyak digit, atau nomor apa yang valid dalam digit tersebut, itu hanya memverifikasi bahwa hanya digit, tanda kurung, tanda hubung, plus, spasi, pound, tanda bintang, titik, koma, atau huruf e, x, t hadir.

Ini harus kompatibel dengan angka internasional dan format lokalisasi. Apakah Anda memperkirakan perlunya mengizinkan tanda kurung siku, keriting, atau siku untuk beberapa wilayah? (saat ini mereka tidak termasuk).

Jika Anda ingin mempertahankan aturan per digit (seperti di Kode Area AS dan Prefixes (kode tukar) harus jatuh dalam kisaran 200-999) baik, semoga sukses untuk Anda. Mempertahankan aturan yang rumit yang bisa menjadi usang di masa depan oleh negara mana pun di dunia tidak terdengar menyenangkan.

Dan ketika menghapus semua / sebagian besar karakter non-numerik dapat bekerja dengan baik di sisi server (terutama jika Anda berencana untuk meneruskan nilai-nilai ini ke dialer), Anda mungkin tidak ingin mencoret input pengguna selama validasi, terutama jika Anda ingin mereka melakukan koreksi di bidang lain.


18



Apakah Anda sudah melihat RegExLib?

Memasuki nomor telepon AS membawa kembali sejumlah kemungkinan.


14