Будет ли это регулярное выражение для этих строк текста? - PullRequest
1 голос
/ 02 марта 2010

Regex:

String regexp = "([0-9.]{1,15})[ \t]*([0-9]{1,15})[ \t]*([0-9.]{1,15})[ \t]*(\"(.*?)\"\\s+\\((\\d{4})\\)\\s+\\{(.*?)\\})";

Текст: * * 1004

1000000103      50   4.5  #1 Single (2006)
2...1.2.12       8   2.7  $1,000,000 Chance of a Lifetime (1986)
11..2.2..2       8   5.0  $100 Taxi Ride (2001)
....13.311       9   7.1  $100,000 Name That Tune (1984)
3..21...22      10   4.6  $2 Bill (2002)
30010....3      18   2.7  $25 Million Dollar Hoax (2004)
2000010002     111   5.6  $40 a Day (2002)
2000000..4      26   1.6  $5 Cover (2009)
.0..2.0122      15   7.8  $9.99 (2003)
..2...1113       8   7.5  $weepstake$ (1979)
0000000125    3238   8.7   Allo  Allo! (1982)
1....22.12       8   6.5   Allo  Allo! (1982) {A Barrel Full of Airmen (#7.7)

Я пытаюсь использовать Java и MySQL вместе. Я изучаю это для проекта, который я планирую. Я хочу, чтобы желаемый результат был таким:

distribution = first column
rank = second column
votes = thirst column 
title = fourth column

Первые три работают нормально. У меня проблемы с четвертым.

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

0...001122      16   7.8  "'Allo 'Allo!" (1982) {Gruber Does Some Mincing (#3.2)}
100..01103      21   7.4  "'Allo 'Allo!" (1982) {Hans Goes Over the Top (#4.1)}
....022100      11   6.9  "'Allo 'Allo!" (1982) {Hello Hans (#7.4)}
0....03022      21   8.4  "'Allo 'Allo!" (1982) {Herr Flick's Revenge (#2.6)}
......8..1       6   7.0  "'Allo 'Allo!" (1982) {Hitler's Last Heil (#8.3)}
.....442..       5   6.5  "'Allo 'Allo!" (1982) {Intelligence Officers (#6.5)}
....1123.2       9   6.9  "'Allo 'Allo!" (1982) {It's Raining Italians (#6.2)}
....1.33.3      10   7.8  "'Allo 'Allo!" (1982) {Leclerc Against the Wall (#5.18)}
....22211.       8   6.4  "'Allo 'Allo!" (1982) {Lines of Communication (#7.5)}

Код, который я использую:

  stmt.executeUpdate("CREATE TABLE mytable(distribution char(20)," +
      "votes integer," + "rank float," + "title char(250));");
  String regexp ="([\\d\\.]+)\\s+(\\d+)\\s+([\\d\\.]+)\\s+(.*?\\s+\\(\\d{4}\\).*)";
  Pattern pattern = Pattern.compile(regexp);
  String line;
  String data= "";
  while ((line = bf.readLine()) != null) {
    data = line.replaceAll("'", " ");
    String data2 = data.replaceAll("\"", "");
    //System.out.println(data2);
    Matcher matcher = pattern.matcher(data2);
    if (matcher.find()) {
        String distribution = matcher.group(1);
        String votes = matcher.group(2);
        String rank = matcher.group(3);
        String title = matcher.group(4);
        //System.out.println(distribution + " " + votes + " " + rank + " " + title);
        String todo = ("INSERT into mytable " +
            "(Distribution, Votes, Rank, Title) "+
            "values ('"+distribution+"', '"+votes+"', '"+rank+"', '"+title+"')");
        stmt = con.createStatement();
        int r = stmt.executeUpdate(todo);
    }
  }

Ответы [ 8 ]

3 голосов
/ 02 марта 2010
/Allo Allo! \(1982\) \{A Barrel Full of Airmen \(\#7\.7\)\}/
2 голосов
/ 02 марта 2010

Можете ли вы использовать split вместо этого и просто разделить его на вкладках? Или получите библиотеку opencsv и используйте ее.

Возможно, что-то вроде

....

String[] temp;
String the_line;
BufferedReader in = new BufferedReader(new FileReader("file.txt")); 

while ((the_line = in.readLine()) != null)
{
    temp = the_line.split("\t");
    ....
}

....
1 голос
/ 02 марта 2010

Попробуйте это

        BufferedReader reader = new BufferedReader(new FileReader("yourFile"));

        Pattern p = Pattern.compile("([0-9\\.]+)[\\s]+([0-9]+)[\\s]+([0-9]\\.[0-9])[\\s]+([^\\s].*$)");

        String line;
        while( (line = reader.readLine()) != null ) {
            Matcher m = p.matcher(line);
            if ( m.matches() ) {
                 System.out.println(m.group(1));
                 System.out.println(m.group(2));
                 System.out.println(m.group(3));
                 System.out.println(m.group(4));
            }

        }

Предполагается, что третья группа состоит только из одной цифры a. и тогда только одна цифра

1 голос
/ 02 марта 2010

Помните правило программирования № 1: будьте проще! Зачем вам действительно нужно регулярное выражение для всего этого?

Мне кажется, что у вас есть хорошо определенный табличный формат ... это в tsv?

Если нет, то вы можете читать построчно, разделять по пробелам для первых 3 столбцов, тогда только для анализа вашего последнего столбца потребуется регулярное выражение.

0 голосов
/ 02 марта 2010

Не используйте регулярные выражения для разбора текста. Regex предназначен для сопоставления шаблонов в тексте, а не для разбора текста по частям / компонентам.

Если пример текстового файла в вашем вопросе является примером фактическим и без изменений , то следующий основной базовый пример "парсера" должен просто работать (в качестве бонуса также мгновенно выполняет необходимый код JDBC). Я скопировал ваши данные без изменений в c:\test.txt.

public static void main(String... args) throws Exception {
    final String SQL = "INSERT INTO movie (distribution, votes, rank, title) VALUES (?, ?, ?, ?)";
    Connection connection = null;
    PreparedStatement statement = null;
    BufferedReader reader = null;        

    try {
        connection = database.getConnection();
        statement = connection.prepareStatement(SQL);
        reader = new BufferedReader(new InputStreamReader(new FileInputStream("/test.txt")));

        // Loop through file.
        for (String line; (line = reader.readLine()) != null;) {
            if (line.isEmpty()) continue; // I am not sure if those odd empty lines belongs in your file, else this if-check can be removed.

            // Gather data from lines.
            String distribution = line.substring(0, 10);
            int votes = Integer.parseInt(line.substring(12, 18).trim());
            double rank = Double.parseDouble(line.substring(20, 24).trim());
            String title = line.substring(26).trim().replace("\"", ""); // You also want to get rid of those double quotes, huh? I am however not sure why, maybe you initially had problems with it in your non-prepared SQL string...

            // Just to show what you've gathered.
            System.out.printf("%s, %5d, %.1f, %s%n", distribution, votes, rank, title);

            // Now add batch to statement.
            statement.setString(1, distribution);
            statement.setInt(2, votes);
            statement.setDouble(3, rank);
            statement.setString(4, title);
            statement.addBatch();
        }

        // Execute batch insert!
        statement.executeBatch();
    } finally {
        // Gently close expensive resources, you don't want to leak them!
        if (reader != null) try { reader.close(); } catch (IOException logOrIgnore) {}
        if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
        if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
    }
}

Видите, это просто работает. Нет необходимости в слишком сложном регулярном выражении.

0 голосов
/ 02 марта 2010

Может быть: [a-zA-Z ]+\!\(\d{4}\) \{[a-zA-Z0-9 \(\)\#\.]+\}

Не уверен, что вы пытаетесь достичь, так что это своего рода предположение ...

Для лучшей помощи вам нужно предоставить более подробную информацию: Еще несколько примеров строк. Что это за данные, вы просто хотите найти совпадение или вам нужны конкретные группы захвата?

0 голосов
/ 02 марта 2010

Это гораздо более простое регулярное выражение, чтобы делать то, что вы хотите сделать

([\d\.]*)\s*([\d\.]*)\s*([\d\.]*)\s*(.*)

Если вам нужно заполнить пробел в конце строки, а также \ s *

([\d\.]*)\s*([\d\.]*)\s*([\d\.]*)\s*(.*)\s*

Я только что исправил небольшую ошибку, используя \ S вместо [\ d.]

0 голосов
/ 02 марта 2010

Нет, не будет.

  1. [ \t] должно стать [ \t]+ или \s+; Ваши числа выровнены по правому краю с использованием пробелов (в дополнение к вкладкам, если они есть) в вводном примере
  2. обратные косые черты должны быть дважды экранированы внутри строковых литералов

Учитывая, что вы хотите, чтобы результат заголовка для "'Allo 'Allo" был Title = Allo Allo! (1982) {Lines of Communication (#7.5)} try:

pattern = "([0-9\\.]+)[ \\t]+([0-9]+)[ \\t]+([0-9\\.]+)[ \\t]+(.*?[ \\t]+\\([0-9]{4}\\).*)";

или (упрощенно, как предложил Фадриан):

pattern = "([\\d\\.]+)\\s+(\\d+)\\s+([\\d\\.]+)\\s+(.*?\\s+\\(\\d{4}\\).*)";

Подробнее о Обратной косой черты, экранировании и цитировании в разделе с таким именем Pattern javadoc page.

...