java 正则表达式的应用:读取文件,获取其中的电话号码详解编程语言

1、正则表达式

  正则表达式,又称正规表示法常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

  用到的一些特殊构造正则表达式的意义解析:

?
当该字符 紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的 贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
.点
匹配除“/r/n”之外的任何单个字符。要匹配包括“/r/n”在内的任何字符,请使用像“[/s/S]”的模式。
(pattern)
匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“/(”或“/)”。
(?:pattern)
匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern)
正向肯定 预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例 如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配 “Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从 包含预查的字符之后开始。
(?!pattern)
正向否定 预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如 “Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中 的“Windows”。
(?<=pattern)
反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
(?<!pattern)
反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。

  量词使用

X{n}? X,恰好 n
X{n,}? X,至少 n
X{n,m}? X,至少 n 次,但是不超过 m

2、手机号码

  组成

国家区域号-手机号码

  手机号码格式比较固定,无非是13x xxxx xxxx或者15x xxxx xxxx再或者18x xxxx xxxx的格式。座机就比较麻烦,比如长途区号变长(3位或者4位)电话号码变长(7位或者8位)有些还需要输入分机号。 

  通常可以看到解决这个复杂问题的解决方案是手机号和座机号分开。座机号拆分成三段,区号,电话号码+分机号。但是为了表单看起来清爽,设计的时候给了一个“万能”的输入框,给用户输入电话号码或者手机号码。 

  在这样的一个需求的大前提下,用复杂的正则表达式解决验证的问题是一种快速的解决方案。 

  首先搞定最容易的手机号码

  因为目前开放的号段是130-139, 150-159, 185-189, 180 

  只考虑移动电话(手机)号码的可以使用下面方法

public static void main(String[] args) {  
String text = "13522158842;托尔斯泰;test2;13000002222;8613111113313";  
Pattern pattern = Pattern.compile("(?<!//d)(?:(?:1[358]//d{9})|(?:861[358]//d{9}))(?!//d)");  
Matcher matcher = pattern.matcher(text);  
    StringBuffer bf = new StringBuffer(64);  
    while (matcher.find()) {  
      bf.append(matcher.group()).append(",");  
    }  
    int len = bf.length();  
    if (len > 0) {  
      bf.deleteCharAt(len - 1);  
    }  
    
System.out.println(bf.toString());  
}

  只是手机号码可以匹配可以给出下面的匹配正则表达式:

(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+//d{8})

  当我们加上国家区域号(86)或者(+86)或者86-或者直接是86,可以使用下面的正则表达式:

          "(?:(//(//+?86//))((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+//d{8})|" +      
                "(?:86-?((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+//d{8})|" + 
                "(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+//d{8})"

  注意:为了最长得匹配电话号码,需要写成三句,并且相对长的需要放在前面,否则匹配到了之后,后面的就不会匹配了。

3、座机号码

   组成:

国家区域号(+86等)-区号-固定电话号码-分机号

三位区号的部分

  010, 021-029,852(香港)

因为采用三位区号的地方都是8位电话号码,因此可以写成

  (010|021|022|023|024|025|026|027|028|029|852)/d{8}

当然不会这么简单,有些人习惯(010) xxxxxxxx的格式,我们也要支持一把,把以上表达式升级成

再看4位区号的城市

  这里简单判断了不可能存在0111或者0222的区号,以及电话号码是7位或者8位。

 最后是分机号(1-4位的数字)

  (?<分机号>/D?/d{1,4})? 

以上拼装起来就是:

"(?:(//(//+?86//))(0[0-9]{2,3}//-?)?([2-9][0-9]{6,7})+(//-[0-9]{1,4})?)|" + 
"(?:(86-?)?(0[0-9]{2,3}//-?)?([2-9][0-9]{6,7})+(//-[0-9]{1,4})?)"

4、编码实现

  实现功能:读取文件,将其中的电话号码存入一个Set返回。

 方法介绍:

find():尝试查找与该模式匹配的输入序列的下一个子序列。

group():返回由以前匹配操作所匹配的输入子序列。

1》、从一个字符串中获取出其中的电话号码

import java.util.HashSet; 
import java.util.Set; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 
 
/** 
 * 从字符串中截取出电话号码 
 * @author zcr 
 * 
 */ 
public class CheckIfIsPhoneNumber  
{ 
     
    /** 
     * 获得电话号码的正则表达式:包括固定电话和移动电话 
     * 符合规则的号码: 
     *     1》、移动电话 
     *         86+‘-’+11位电话号码 
     *         86+11位正常的电话号码 
     *         11位正常电话号码a 
     *         (+86) + 11位电话号码 
     *         (86) + 11位电话号码 
     *     2》、固定电话 
     *         区号 + ‘-’ + 固定电话  + ‘-’ + 分机号 
     *         区号 + ‘-’ + 固定电话  
     *         区号 + 固定电话 
     * @return    电话号码的正则表达式 
     */ 
    public static String isPhoneRegexp() 
    { 
        String regexp = ""; 
         
        //能满足最长匹配,但无法完成国家区域号和电话号码之间有空格的情况 
        String mobilePhoneRegexp = "(?:(//(//+?86//))((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+//d{8})|" +      
                "(?:86-?((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+//d{8})|" + 
                "(?:((13[0-9]{1})|(15[0-9]{1})|(18[0,5-9]{1}))+//d{8})"; 
         
         
         
        //    System.out.println("regexp = " + mobilePhoneRegexp); 
        //固定电话正则表达式 
         
        String landlinePhoneRegexp = "(?:(//(//+?86//))(0[0-9]{2,3}//-?)?([2-9][0-9]{6,7})+(//-[0-9]{1,4})?)|" + 
                "(?:(86-?)?(0[0-9]{2,3}//-?)?([2-9][0-9]{6,7})+(//-[0-9]{1,4})?)";     
 
        regexp += "(?:" + mobilePhoneRegexp + "|" + landlinePhoneRegexp +")";  
     
        return regexp; 
    } 
     
     
    /** 
     * 从dataStr中获取出所有的电话号码(固话和移动电话),将其放入Set 
     * @param dataStr    待查找的字符串 
     * @param phoneSet    dataStr中的电话号码 
     */ 
    public static void getPhoneNumFromStrIntoSet(String dataStr,Set<String> phoneSet) 
    { 
        //获得固定电话和移动电话的正则表达式 
        String regexp = isPhoneRegexp(); 
         
        System.out.println("Regexp = " + regexp); 
         
        Pattern pattern = Pattern.compile(regexp);  
        Matcher matcher = pattern.matcher(dataStr);  
 
        //找与该模式匹配的输入序列的下一个子序列 
        while (matcher.find())  
        {  
            //获取到之前查找到的字符串,并将其添加入set中 
            phoneSet.add(matcher.group()); 
        }  
        //System.out.println(phoneSet); 
    } 
}

2、读取文件并调用电话号码获取

  实现方式:根据文件路径获得文件后,一行行读取,去获取里面的电话号码

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.InputStreamReader; 
import java.util.ArrayList; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Set; 
 
 
 
/** 
 * 读取文件操作 
 *  
 * @author zcr 
 *  
 */ 
public class ImportFile 
{ 
    /** 
     * 读取文件,将文件中的电话号码读取出来,保存在Set中。 
     * @param filePath    文件的绝对路径 
     * @return            文件中包含的电话号码 
     */ 
    public static Set<String> getPhoneNumFromFile(String filePath) 
    { 
        Set<String> phoneSet = new HashSet<String>(); 
         
        try 
        { 
            String encoding = "UTF-8"; 
            File file = new File(filePath); 
            if (file.isFile() && file.exists()) 
            { // 判断文件是否存在 
                InputStreamReader read = new InputStreamReader( 
                        new FileInputStream(file), encoding);// 考虑到编码格 
                BufferedReader bufferedReader = new BufferedReader(read); 
                String lineTxt = null; 
 
                while ((lineTxt = bufferedReader.readLine()) != null) 
                { 
                    //读取文件中的一行,将其中的电话号码添加到phoneSet中 
                    CheckIfIsPhoneNumber.getPhoneNumFromStrIntoSet(lineTxt, phoneSet); 
                } 
                read.close(); 
            } 
            else 
            { 
                System.out.println("找不到指定的文件"); 
            } 
        } 
        catch (Exception e) 
        { 
            System.out.println("读取文件内容出错"); 
            e.printStackTrace(); 
        } 
         
        return phoneSet; 
    } 
 
}

3》、测试

public static void main(String argv[]) 
    { 
        String filePath = "F://three.txt";     
         
        Set<String> phoneSet = getPhoneNumFromFile(filePath); 
         
        System.out.println("电话集合:" + phoneSet); 
    }

 

文件中数据:

java 正则表达式的应用:读取文件,获取其中的电话号码详解编程语言

结果:

电话集合:[86132221, (86)13222144332, 86-13222144332, 32434343, (+86)13222144332, 13888888888]

  致谢:感谢您的阅读!

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/15128.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论