Как можно объединить строки в файле CSV, если в одном из полей есть новая строка? - PullRequest
1 голос
/ 10 ноября 2008

Если у меня есть файл, разделенный запятыми, как показано ниже:

foo,bar,n
,a,bc,d
one,two,three
,a,bc,d

И я хочу присоединиться к \n,, чтобы произвести это:

foo,bar,n,a,bc,d
one,two,three,a,bc,d

Что такое трюк с регулярными выражениями? Я думал, что if (/\n,/) поймает это.

Кроме того, нужно ли мне делать что-то особенное для файла в кодировке UTF-8?

Наконец, решение в Groovy также будет полезно.

Ответы [ 5 ]

12 голосов
/ 10 ноября 2008

Вы должны использовать Text :: CSV_XS вместо того, чтобы делать это самостоятельно. Он поддерживает новые строки, встроенные в записи, а также файлы Unicode. Вам нужно указать правильные параметры при создании парсера, поэтому обязательно внимательно прочитайте документацию.

0 голосов
/ 13 ноября 2008

Это в первую очередь ответ на ваш вопрос о кодировке UTF-8.

В зависимости от конкретной кодировки, вам может также нужно искать нулевые байты. Если приведенный выше совет не сработал, замена 's / \ n, /, / g' на 's / \ c @? \ N (\ c @ ?,) / $ 1 / g' может работать без нарушения кодировки хотя может быть безопаснее делать это итеративно (применяя 's / \ c @? \ n (\ c @ ?,) / $ 1 /' к каждой строке вместо того, чтобы объединять их и применять это глобально). Это действительно взлом, а не замена реальной поддержки юникода, но если вам просто нужно быстрое исправление или если у вас есть гарантии относительно кодировки, это может помочь.

0 голосов
/ 12 ноября 2008

Это может быть слишком просто (или недостаточно хорошо обрабатывать общий случай),

def input = """foo,bar,n
,a,bc,d
one,two,three
,a,bc,d"""

def last
input.eachLine {
    if(it.startsWith(',')) {
        last += it;
        return;
    }
    if(last)
        println last;
    last = it
}
println last

испускает;

foo,bar,n,a,bc,d
one,two,three,a,bc,d
0 голосов
/ 11 ноября 2008

Вот отличная версия. В зависимости от требований, есть некоторые нюансы, которые могут не учитываться (например, строки в кавычках, которые могут содержать запятые). Также необходимо настроить, если новая строка может произойти в середине поля, а не всегда в конце.

def input = """foo,bar,n
,a,bc,d
one,two,three
,a,bc,d"""

def answer = (input =~ /(.*\n?,){5}.*(\n|$)/).inject ("") { ans, match  ->
    ans << match.replaceAll("\n","") << "\n"
}

assert answer.toString() == 
"""foo,bar,n,a,bc,d
one,two,three,a,bc,d
"""
0 голосов
/ 10 ноября 2008

Это работает для меня:

open(F, "test.txt") or die;
undef $/;
$s = <F>;
close(F);
$s =~ s/\n,/,/g;
print $s;

$ cat test.txt
foo,bar,n
,a,bc,d
one,two,three
,a,bc,d
$ perl test.pl 
foo,bar,n,a,bc,d
one,two,three,a,bc,d
...