2012-07-13 2 views
12

Файл names.txt состоит из множества имен в виде:strings.Split в Go

"KELLEE","JOSLYN","JASON","INGER","INDIRA","GLINDA","GLENNIS" 

Кто-нибудь знает, как разбить строку таким образом, что это отдельные имена, разделенные запятыми?

KELLEE,JOSLYN,JASON,INGER,INDIRA,GLINDA,GLENNIS 

Следующий код расщепляется запятой и оставляет кавычки вокруг имени, что экранирующий символ для разделения вне ". Можно ли это сделать в одном заявлении Split, разделив "," и оставив запятую для разделения?

package main 

import "fmt" 
import "io/ioutil" 
import "strings" 

func main() { 
     fData, err := ioutil.ReadFile("names.txt") // read in the external file 
    if err != nil { 
     fmt.Println("Err is ", err)  // print any error 
    } 
    strbuffer := string(fData) // convert read in file to a string 

    arr := strings.Split(strbuffer, ",") 

    fmt.Println(arr) 

} 

Кстати, это часть проекта Эйлера проблемы # 22. http://projecteuler.net/problem=22

ответ

18

Ответ Джереми в основном правильный и делает именно то, о чем вы просили. Но формат вашего файла «names.txt» на самом деле хорошо известен и называется CSV (значения, разделенные запятой). К счастью, Go поставляется с пакетом encoding/csv (который является частью стандартной библиотеки) для упрощения декодирования и кодирования таких форматов. В дополнение к вашему решению + Джереми, этот пакет также будет давать точные сообщения об ошибках, если формат недействителен, поддерживает многострочные записи и делает правильную неквалификацию цитируемых строк.

Основное использование выглядит следующим образом:

package main 

import (
    "encoding/csv" 
    "fmt" 
    "io" 
    "os" 
) 

func main() { 
    file, err := os.Open("names.txt") 
    if err != nil { 
     fmt.Println("Error:", err) 
     return 
    } 
    defer file.Close() 
    reader := csv.NewReader(file) 
    for { 
     record, err := reader.Read() 
     if err == io.EOF { 
      break 
     } else if err != nil { 
      fmt.Println("Error:", err) 
      return 
     } 

     fmt.Println(record) // record has the type []string 
    } 
} 

Существует также ReadAll метод, который может сделать вашу программу еще короче, если предположить, что весь файл помещается в памяти.

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

for { 
    if n, _ := fmt.Fscanf(file, "%q,", &name); n != 1 { 
     break 
    } 
    fmt.Println("name:", name) 
} 
+0

На самом деле это не файл csv, поскольку есть только одна строка: http://projecteuler.net/project/names.txt –

+0

О, вы правы. Это CSV-файл с одной строкой :) – tux21b

+1

Плюс один для использования Fscanf :-) –

9

Split не удаляет символы из подстрок. Ваш раскол прекрасно вам просто нужно обработать срез впоследствии с strings.Trim (Валя, «\» «).

for i, val := range arr { 
    arr[i] = strings.Trim(val, "\"") 
} 

Теперь обр будет иметь начальные и завершающие» ы удалены.

+2

Обратите внимание, что это не будет работать: '«Smithe, П.»,«Пупкин, J.» ' – Timmmm

Смежные вопросы