Сопоставитель многострочных регулярных выражений

Есть входной файл с содержанием:
XX00002200000
XX00003300000

регулярное выражение:

(.{6}22.{5}\W)(.{6}33.{5})

Пробовал в The Regex Coach (приложение для тестирования регулярных выражений), строки сопоставляются нормально.

Ява:

        pattern = Pattern.compile(patternString);
        inputStream = resource.getInputStream();

        scanner = new Scanner(inputStream, charsetName);
        scanner.useDelimiter("\r\n");

patternString - это регулярное выражение (упомянутое выше), добавленное как свойство компонента из .xml

Это не удалось с Java.


person sergionni    schedule 11.10.2010    source источник
comment
Что такое patternString? Что ты ему назначил? Как вы его назначили? Вы уверены, что ваши обратные косые черты являются буквальными обратными косыми чертами в регулярном выражении?   -  person PP.    schedule 11.10.2010
comment
Не говоря уже о том, где вы на самом деле используете шаблон?   -  person Pace    schedule 11.10.2010
comment
@Pace, который я использую: String val = scan.next(pattern);   -  person sergionni    schedule 11.10.2010


Ответы (3)


Простое решение: ".{6}22.{5}\\s+.{6}33.{5}". Обратите внимание, что \s+ – это сокращение для последующих пробельных элементов.

Вот пример:

 public static void main(String[] argv) throws FileNotFoundException {
  String input = "yXX00002200000\r\nXX00003300000\nshort", regex = ".{6}22.{5}\\s+.{6}33.{5}", result = "";
  Pattern pattern = Pattern.compile(regex);
  Matcher m = pattern.matcher(input);

  while (m.find()) {
   result = m.group();
   System.out.println(result);
  }
 }

С выходом:

XX00002200000
XX00003300000

Чтобы поиграть с Java Regex, вы можете использовать: Редактор регулярных выражений (бесплатный онлайн-редактор)

Изменить: я думаю, что вы меняете ввод при чтении данных, попробуйте:

public static String readFile(String filename) throws FileNotFoundException {
    Scanner sc = new Scanner(new File(filename));

    StringBuilder sb = new StringBuilder();
    while (sc.hasNextLine())
        sb.append(sc.nextLine());
    sc.close();

    return sb.toString();
}

Or

static String readFile(String path) {
    FileInputStream stream = null;
    FileChannel channel = null;
    MappedByteBuffer buffer = null;

    try {
        stream = new FileInputStream(new File(path));
        channel = stream.getChannel();
        buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0,
                channel.size());
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            stream.close();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }

    return Charset.defaultCharset().decode(buffer).toString();
}

С импортом, как:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
person Margus    schedule 11.10.2010
comment
Привет, Маргус. Это интересно, я попробовал предложенное вами регулярное выражение:.{6}22.{5}\\s+.{6}33.{5} в приложении The Regex Coach. Он работает нормально (без обратной косой черты). Из Java id не работает, очень странно. - person sergionni; 11.10.2010
comment
Должен ли я каким-то образом преобразовать InputStrem в FileInputStream, чтобы вызвать метод getChannel()? - person sergionni; 11.10.2010

Попробуйте это изменение в разделителе:

 scanner.useDelimiter("\\s+");

также почему бы вам не использовать более общее регулярное выражение, подобное этому:

 ".{6}[0-9]{2}.{5}"

Регулярное выражение, которое вы упомянули выше, предназначено для 2 строк. Поскольку вы упомянули разделитель как новую строку, вы должны указать выражение регулярного выражения, подходящее для одной строки.

person Emil    schedule 11.10.2010
comment
спасибо за ответ, это регулярное выражение необходимо для извлечения определенного строкового буфера из очереди сообщений, этот строковый буфер начинается со строки с 22 и заканчивается строкой с 33. И на самом деле между этими строками будут строки схожей структуры, разделенные LR или LF также. - person sergionni; 11.10.2010
comment
Я не совсем понял. Помог ли вам мой ответ? Если нет, пожалуйста, подробно объясните вышеуказанную проблему, отредактировав свой вопрос. - person Emil; 11.10.2010

Простите мое невежество, но я до сих пор не уверен, что именно вы пытаетесь найти. В случае, если вы пытаетесь найти строку (с новыми строками)

XX00002200000
XX00003300000

тогда почему вы читаете его, разделяя его новыми строками?

Чтобы прочитать приведенную выше строку как есть, работает следующий код

Pattern p = Pattern.compile(".{6}22.{5}\\W+.{6}33.{5}");

 FileInputStream scanner = null;
        try {
            scanner = new FileInputStream("C:\\new.txt");
            {
                byte[] f = new byte[100];
                scanner.read(f);
                String s = new String(f);
                Matcher m = p.matcher(s);
                if(m.find())
                    System.out.println(m.group());
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

NB: здесь файл new.txt содержит строку

XX00002200000
XX00003300000
person Gaurav Saxena    schedule 11.10.2010
comment
как использовать сканер с InputStream? в случае сканера = новый сканер (inputStream, charsetName), он не поддерживает чтение метода - person sergionni; 12.10.2010
comment
Я не уверен, почему вам так необходимо использовать Scanner для чтения из файла, но если это так, то лучше всего использовать разделитель, который не будет найден в файле, например. сканер.useDelimiter(\\?); Это предложит сканеру получить всю строку из файла. - person Gaurav Saxena; 13.10.2010