2009-12-23 3 views
1

У меня есть несколько строк, которые в следующем формате:
12/18/2009 02:08:26 Допускаются Doe, John (Card # 111) в Южной Lobby [В]

Из этой строки мне нужно выбрать дату, время, имя и фамилию человека и номер карты. Слово допустимое может быть опущено, и все, что следует за последней цифрой номера карты, можно игнорировать.
У меня такое чувство, что я хочу использовать StringTokenizer для этого, но я не уверен.
Любые предложения?Разбиение строки в Java

+0

Если это файл, который вы читаете из, я был бы соблазн обработать его и сохранить его во втором файле, скажем, в формате CSV, это легче обрабатывать. Это связано с тем, что полевая информация может содержать пробелы. Либо это, либо изменить способ его кодирования. –

ответ

2

Ваш формат записи достаточно просто, что я бы просто использовать split строковый метод, чтобы получить дату и время. Как отмечалось в комментариях, наличие имен, которые могут содержать пробелы, усложняет вещи настолько, что разделение записи пробелами не будет работать для каждого поля. Я использовал регулярное выражение, чтобы захватить остальные три части информации.

public static void main(String[] args) { 
    String record1 = "12/18/2009 02:08:26 Admitted Doe, John (Card #111) at South Lobby [In]"; 
    String record2 = "12/18/2009 02:08:26 Admitted Van Halen, Eddie (Card #222) at South Lobby [In]"; 
    String record3 = "12/18/2009 02:08:26 Admitted Thoreau, Henry David (Card #333) at South Lobby [In]"; 

    summary(record1); 
    summary(record2); 
    summary(record3); 
} 

public static void summary(String record) { 
    String[] tokens = record.split(" "); 

    String date = tokens[0]; 
    String time = tokens[1]; 

    String regEx = "Admitted (.*), (.*) \\(Card #(.*)\\)"; 
    Pattern pattern = Pattern.compile(regEx); 
    Matcher matcher = pattern.matcher(record); 
    matcher.find(); 

    String lastName = matcher.group(1); 
    String firstName = matcher.group(2); 
    String cardNumber = matcher.group(3); 

    System.out.println("\nDate: " + date); 
    System.out.println("Time: " + time); 
    System.out.println("First Name: " + firstName); 
    System.out.println("Last Name: " + lastName); 
    System.out.println("Card Number: " + cardNumber); 
} 

Регулярное выражение "Admitted (.*), (.*) \\(Card #(.*)\\)" использует группировку круглых скобок для хранения информации, которую вы пытаетесь извлечь. Скобки, которые существуют в вашей записи, должны быть экранированы.

Выполнение кода выше, дает мне следующий вывод:

Date: 12/18/2009 
Time: 02:08:26 
First Name: John 
Last Name: Doe 
Card Number: 111 

Date: 12/18/2009 
Time: 02:08:26 
First Name: Eddie 
Last Name: Van Halen 
Card Number: 222 

Date: 12/18/2009 
Time: 02:08:26 
First Name: Henry David 
Last Name: Thoreau 
Card Number: 333 
+2

Приятно, но это ломается для имен с пробелами в них. Например, «Van Halen, Eddie» –

+0

@Adriaan: Спасибо, что указали это. Данные в реальном мире - такая боль иногда! :) Я изменил свой код, чтобы использовать регулярные выражения, чтобы вытащить те части данных, на которые повлияли пробелы в именах. –

+0

Спасибо, Билл. Это сработало отлично. – clang1234

-1

Доверяйте своим кишок ... :) С StringTokenizer:

import java.io.*; 
import java.util.StringTokenizer; 
public class Test { 
    public Test() { 
    }

public void execute(String str) { String date, time, firstName, lastName, cardNo; StringTokenizer st = new StringTokenizer(str, " "); date = st.nextToken(); time = st.nextToken(); st.nextToken(); //Admitted lastName = st.nextToken(",").trim(); firstName = st.nextToken(",(").trim(); st.nextToken("#"); //Card cardNo = st.nextToken(")#"); System.out.println("date = " + date +"\ntime = " + time +"\nfirstName = " + firstName +"\nlastName = "+ lastName +"\ncardNo = " +cardNo); }

public static void main(String args[]) { Test t = new Test(); String record1 = "12/18/2009 02:08:26 Admitted Doe, John (Card #111) at South Lobby [In]"; String record2 = "12/18/2009 02:08:26 Admitted Van Halen, Eddie (Card #222) at South Lobby [In]"; String record3 = "12/18/2009 02:08:26 Admitted Thoreau, Henry David (Card #333) at South Lobby [In]"; t.execute(record1); t.execute(record2); t.execute(record3); } }

+0

Спасибо, но используя StringTokenizer, как бы я сломал цепочку? – clang1234

+0

Я отредактировал ответ с тем же :) – bhups

3

Строка Tokenizer является большим, когда у вас есть общий ограничитель, но в данном случае я выбрал бы для регулярных выражений.

+1

+1 для регулярного выражения. – Ross

+0

Как пример для вычеркивания даты из строки, я пытаюсь сделать следующее: Дата созданияPattern = Pattern.compile ("[0-9] {2}/[0-9] {2}/[0-9] {4}"); Затем, используя Matcher на строке, с этим шаблоном, я не получаю результата. Как правильно форматировать это регулярное выражение? – clang1234

+0

Судебная и ошибка: http://www.regexplanet.com/simple/ –

2

Я бы пошел на java.util.Scanner ... этот код поможет вам начать ... вы должны действительно использовать форму шаблона методов сканера, а не форму String, которую я использовал.

import java.util.Scanner; 

public class Main 
{ 
    public static void main(String[] args) 
     throws Exception 
    { 
     final String str; 
     final Scanner scanner; 
     final String date; 
     final String time; 
     final String word; 
     final String lastName; 
     final String firstName; 

     str  = "12/18/2009 02:08:26 Admitted Doe, John (Card #111) at South Lobby [In]"; 
     scanner = new Scanner(str); 
     date  = scanner.next("\\d+/\\d+/\\d+"); 
     time  = scanner.next("\\d+:\\d+:\\d+"); 
     word  = scanner.next(); 
     lastName = scanner.next(); 
     firstName = scanner.next(); 
     System.out.println("date : " + date); 
     System.out.println("time : " + time); 
     System.out.println("word : " + word); 
     System.out.println("last : " + lastName); 
     System.out.println("first: " + firstName); 
    } 
} 
1

Несколько вещей, чтобы иметь в виду, в то время как вы разбираем эту строку:

  • Фамилии может иметь пробелы, так что вы должны быть ищу ,
  • имя может иметь пространство так искать для (

В связи с этим я отработаю ответ от TofuBeer и настрою следующий для имени и фамилии. Разделение строк будет грязным из-за дополнительных пробелов.

0

Кратчайший регулярное_выражение решение (с литьем типа):

String stringToParse = "12/18/2009 02:08:26 Admitted Doe, John (Card #111) at South Lobby [In] "; 
Pattern pattern = Pattern.compile("((\\d{2}/){2}\\d{4}\\s(\\d{2}:){2}\\d{2})\\s(\\w+)\\s((.*)),\\s((.*))\\s.*#(\\d+)"); 
Matcher matcher = pattern.matcher(stringToParse); 
matcher.find(); 

String firstName = matcher.group(6); 
String lastName = matcher.group(5); 
int cardNumber = Integer.parseInt(matcher.group(7)); 

DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); 
Date date = df.parse(matcher.group(1));