Есть ли способ обрабатывать данные из текстового файла, содержащего основные заголовки, с помощью регулярного выражения?

Ниже приведен фрагмент структуры формата текстового файла.

Historical Sales for: 12th of October  2019, 11:37 am

PRODUCT NAME      QUANTITY
Coke B            5

Historical Sales for: 21st of October  2019, 8:15 pm

PRODUCT NAME      QUANTITY
Peanuts           2

Я хочу обрабатывать только метки столбцов и значения строк, но не включая основной заголовок; в данном случае История продаж за: 12 октября 2019 г., 11:37.

Это код, который я написал для обработки текста с помощью регулярного выражения (\\b)

        StringBuilder temporary = new StringBuilder();
   
        InputStream inputStream = new FileInputStream(new File(FILE_NAME));            
        BufferedReader readFile = new BufferedReader(new InputStreamReader(inputStream));
        
        String next; 
        
        while ((next = readFile.readLine()) != null) {
           temporary.append(next).append("\n");
        }   

        next = String.format("%13s", ""); // spacing for column headers          
        System.out.println(temporary.toString().replaceAll("(\\b)", next));

person Marome    schedule 18.06.2020    source источник
comment
\\b{3} соответствует пустой строке в каждой позиции границы слова три раза. Итак, эффективное сопоставление пустой строки. \\b{3} = \\b   -  person Wiktor Stribiżew    schedule 18.06.2020
comment
Для образца текстового файла следует использовать предварительно отформатированный текстовый блок (кодовый блок), а не изображение текстового файла. —— Это один текстовый файл с несколькими историческими продажами для: заголовков или несколько файлов, каждый из которых имеет заголовок? Насколько последовательны заголовки? Возможно, вы могли бы сопоставлять и отбрасывать заголовки при обработке файлов, если сами заголовки соответствуют шаблону.   -  person Stephen P    schedule 18.06.2020
comment
for (; <condition> ;) это то же самое, что и while (<condition>)while является гораздо более естественной конструкцией для этого.... while ( line = readFile.readLine() ) != null) { if (isHeaderLine(line) { continue; } temporaryData.append..... }   -  person Stephen P    schedule 18.06.2020
comment
Да было бы неплохо уточнить или строго определить формат файла.   -  person bsaverino    schedule 18.06.2020
comment
регулярное выражение (\\b{3}) соответствует escape-символу, а затем символу b 3 раза. это то, что видит двигатель   -  person    schedule 19.06.2020
comment
просто разобрать текст, обведенный красным, на изображении yuior. были ли какие-либо parrtakular thangs matcherd?   -  person    schedule 19.06.2020
comment
@Stephen P, это один текстовый файл, содержащий заголовок «Исторические продажи для: в нескольких разделах».   -  person Marome    schedule 19.06.2020
comment
@Edward Он соответствует всему тексту в файле, а это не то, что мне нужно. Моя цель состояла в том, чтобы полностью отказаться от заголовков Исторические продажи для: и соответствующей даты со временем.   -  person Marome    schedule 19.06.2020
comment
это регулярное выражение в вашем посте (\\b{3}), механизм регулярных выражений будет соответствовать этому \bbb и только tyhat! какое отношение «Исторические сайты» имеют к этому регулярному выражению?   -  person    schedule 21.06.2020
comment
@Edward, чтобы добавить пробелы в исторические продажи для использования описателя формата %13s. Я исправлен, поскольку @Wiktor Stribiżew ясно указал на неэффективность моего регулярного выражения с помощью оператора \\b{3} = \\b   -  person Marome    schedule 22.06.2020
comment
потерял меня, я думаю, ты не понимаешь. \\b{3} = \\b опять же не имеет контекста, если обработчик регулярных выражений увидит \\b{3}, он будет соответствовать \ + bbb, тогда как \\b будет соответствовать \ + b .. они явно не совпадают, т.е. \\b{3} != \\b   -  person    schedule 22.06.2020
comment
@ Эдвард, я понимаю использование квантификаторов и точное значение b{3}. Спасибо за конструктивную критику, я буду читать дальше в регулярном выражении   -  person Marome    schedule 23.06.2020
comment
@ Эдвард, просто примечание, \ не будет совпадать. Причина в том, что обратная косая черта является escape-символом в Java, поэтому регулярное выражение \b эквивалентно \\b в языке Java. Вот ссылка, baeldung.com/java-regexp-escape-char, находится в разделе Экранирование с помощью обратной косой черты.   -  person Marome    schedule 23.06.2020
comment
регулярное выражение \\b соответствует a \ + b. демо - › regex101.com/r/XIvBBb/1 . Кроме того, я не знаю \\b in the Java language.   -  person    schedule 25.06.2020
comment
@ Эдвард, спасибо за демонстрацию, она выглядит очень полезной. Что касается интерпретации регулярного выражения \\b, прочитайте здесь stackoverflow.com /questions/8777982/issue-with-java-regex-b для получения дополнительной информации об использовании \b и \\b в языке Java.   -  person Marome    schedule 26.06.2020
comment
@Эдвард, вот демонстрация tpcg.io/BaJ2MYc4, надеюсь, она вам все прояснит   -  person Marome    schedule 26.06.2020


Ответы (1)


Если вы намерены напечатать только строки:

PRODUCT NAME      QUANTITY
Chips             2
Coke B            5

И подобные. Я предлагаю вам использовать потоки Java 8 и использовать приведенное ниже регулярное выражение для удаления ненужных строк:

public static void main(String[] args) throws Exception {
    String collect = Files.lines(Paths.get("file.txt"))
            .filter(line -> !line.matches("^Historical Sales for.*$") && !line.matches("^\\s*$"))
            .map(line -> line+="\n")
            .collect(Collectors.joining());
    System.out.println(collect);
}

Таким образом, у вас будет:

PRODUCT NAME      QUANTITY
Chips             2
Coke B            5
PRODUCT NAME      QUANTITY
(...)

Одним из преимуществ использования Streams является метод .collect(), который позволяет вам анализировать строку непосредственно в файле List.

Если вы хотите сохранить свой пример, вы можете сделать:

StringBuilder temporaryData = new StringBuilder();

InputStream inputStream = new FileInputStream(new File("file.txt"));
BufferedReader readFile = new BufferedReader(new InputStreamReader(inputStream));

String next;

while ((next = readFile.readLine()) != null) {
    temporaryData.append(next).append("\n");
}

next = String.format("%13s", ""); // spacing for column headers
String formattedString = temporaryData.toString().replaceAll("(\\b{3})", next);
String stringWithoutHeaders = formattedString.replaceAll("^Historical Sales for.*$", "").replaceAll("^\\s*$", "");
System.out.println(stringWithoutHeaders);
person fjsv    schedule 18.06.2020
comment
Благодарю вас! Подход Java 8 более читабелен и сделал свое дело :) - person Marome; 19.06.2020