Как я могу объединить строки в файле CSV, если в одном из полей есть новая строка?

StackOverflow https://stackoverflow.com/questions/278692

  •  07-07-2019
  •  | 
  •  

Вопрос

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

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 также было бы полезно.

Это было полезно?

Решение

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

Другие советы

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

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

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

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
"""

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top