Java中的模式和匹配器正则表达式

时间:2014-10-02 21:16:14

标签: java regex

我在Java中使用Pattern和Matcher时遇到了问题..

我试图用它从至少包含.SXXEXX的字符串中提取两个数字。其中XX是我要提取的int。任何正则表达式/ java pro都想帮帮我吗?

这是我最好的尝试,但它会导致运行时异常.. :(

String s = "Some.Cool.Series.S06E01.720p.HDTV.X264-Pewpew";
Pattern p = Pattern.compile("[^.S].S(\\d2)E(\\d+2)\\p{Alpha}");
Matcher m = p.matcher(s);
String season = m.group(0);
String episode = m.group(1);

2 个答案:

答案 0 :(得分:1)

您的正则表达式错误,您需要在访问群组之前调用findmatches方法:

String s = "Some.Cool.Series.S06E01.720p.HDTV.X264-Pewpew";
Pattern p = Pattern.compile("\\.S(\\d{2})E(\\d{2})\\.");
Matcher m = p.matcher(s);
if (m.find() {
   String season = m.group(1);
   String episode = m.group(2);
}

答案 1 :(得分:1)

首先,尽管你的正则表达式有错误,因此无法编译,我必须祝贺你勇敢的努力。即使对于看起来无害且直截了当的案例,也很难从一开始就100%正确使用正则表达式。通过较小的更正,您可以修改它以从字符串中提取所需的信息,假设分隔符是点'。如在您的示例中,季节和剧集以精确的SXXEXX格式给出。以下是该模式的更正版本:"\\.S(\\d{2})E(\\d{2})\\."

您可以分别为季节和剧集调用m.group(1)m.group(2)来访问捕获的群组。引用java.util.regex.Matcher javadoc

  

捕获组从左到右编制索引,从1开始。组零表示整个模式,因此表达式m.group(0)等同于m.group()。

为了增强教学范式,我编写了一个单例(只有一个实例),它是根据第17页的 Effective Java 建议设计的(Bloch J.,第2版​​,2008年)。使用getInstance()方法访问的类的实例公开了parse()方法,该方法接受包含您要提取并解析它的系列信息的字符串,将季节和剧集编号保存到各自的私有整数字段。最后作为测试,我们尝试从各种(虚构)系列中解析一系列挑战性剧集名称 - 包括您自己的例子 - 并看看我们是否可以获得季节和剧集的数量。恕我直言这个例子简明扼要地说明了你想要实现的更广泛的版本,还有:

  1. 重复使用已编译模式的有效方法
  2. 比你想要匹配的限制模式(例如" S"," s","赛季","季节&# 34;,"赛季"是匹配 赛季 关键字的所有可接受的变体)
  3. 如何使用外观和字边界(?<=以及(?=\b
  4. 如何使用(?<name>X)语法使用命名捕获组(请注意:必须使用Java 7或更高版本,有关详细信息,请参阅this older question
  5. 分别如何使用PatternMatcher类的有趣案例。您还可以从 Oracle The Java Tutorials: Regular Expressions
  6. 查看这个非常有教育意义的教程
  7. 如何创建和使用单身人士
  8. //课程开始

    public class SeriesInfoMatcher {
    
        private int season, episode;
        static final String SEASON_EPISODE_PATTERN = "(?<=\\b|_) s(?:eason)? (?<season>\\d+) e(?:pisode)? (?<episode>\\d+) (?=\\b|_)";
        private final Pattern pattern = Pattern.compile(SEASON_EPISODE_PATTERN, Pattern.CASE_INSENSITIVE | Pattern.COMMENTS);
        private Matcher matcher;
        private String seriesInfoString;
        private static SeriesInfoMatcher instance;
    
        private SeriesInfoMatcher() {
            resetFields();
        }
    
        public static SeriesInfoMatcher getInstance() {
            return instance == null ? new SeriesInfoMatcher() : instance;
        }
    
        /**
         * Analyzes a string containing series information and updates the internal fields accordingly
         * @param unparsedSeriesInfo The string containing episode and season numbers to be extracted. Must not be null or empty.
         */
        public void parse (String unparsedSeriesInfo) {
            try {
                if (unparsedSeriesInfo == null || unparsedSeriesInfo.isEmpty()) {
                    throw new IllegalArgumentException("String argument must be non-null and non-empty!");
                }
                seriesInfoString = unparsedSeriesInfo;
                initMatcher();
                while (matcher.find()) {
                    season = Integer.parseInt ( matcher.group("season") );
                    episode = Integer.parseInt( matcher.group("episode"));
                }
            }
            catch (Exception ex) {
                resetFields();
                System.err.printf("Invalid movie info string format. Make sure there is a substring of \"%s\" format.%n%s", "S{NUMBER}E{NUMBER}", ex.getMessage());
            }
        }
    
        private void initMatcher() {
            if (matcher == null) {
                matcher = pattern.matcher(seriesInfoString);
            }
            else {
                matcher.reset(seriesInfoString);
            }
        }
    
        private void resetFields() {
            seriesInfoString = "";
            season = -1;
            episode = -1;
        }
    
        @Override
        public String toString() {
            return seriesInfoString.isEmpty() ? 
                "<no information to display>": 
                String.format("{\"%s\": %d, \"%s\": %d}", "season", season, "episode", episode);
        }
    
        public static void main(String[] args){
            // Example movie info strings
            String[] episodesFromVariousSeries = {
                "Some.Cool.Series.S06E01.720p.HDTV.X264-Pewpew",
                "Galactic Wars - S01E02 - A dire development",
                "A.dotted.hell.season3episode15.when.enough.is.enough.XVID",
                "The_underscore_menace_-_The_horror_at_the_end!_[2012]_s05e02",
                "s05e01_-_The_underscore_menace_-_Terror_at_the_beginning_[2012]"
            };
            SeriesInfoMatcher seriesMatcher = new SeriesInfoMatcher();
            System.out.printf( "%-80s %-20s%n", "Episode Info", "Parsing Results" );
            for (String episode: episodesFromVariousSeries) {
                seriesMatcher.parse(episode);
                System.out.printf( "%-80s %-20s%n", episode, seriesMatcher );
            }
        }
    }
    

    main()的输出是:

    Episode Info                                                                     Parsing Results     
    Some.Cool.Series.S06E01.720p.HDTV.X264-Pewpew                                    {"season": 6, "episode": 1}
    Galactic Wars - S01E02 - A dire development                                      {"season": 1, "episode": 2}
    A.dotted.hell.season3episode15.when.enough.is.enough.XVID                        {"season": 3, "episode": 15}
    The_underscore_menace_-_The_horror_at_the_end!_[2012]_s05e02                     {"season": 5, "episode": 2}
    s05e01_-_The_underscore_menace_-_Terror_at_the_beginning_[2012]                  {"season": 5, "episode": 1}