Comment puis-je joindre des lignes dans un fichier CSV lorsqu'un des champs comporte une nouvelle ligne?

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

  •  07-07-2019
  •  | 
  •  

Question

Si j'ai un fichier séparé par des virgules, comme suit:

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

Et je souhaite rejoindre le \ n, pour produire ceci:

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

Quel est le truc de la regex? Je pensais qu'un if (/ \ n, /) pourrait intercepter cela.

De plus, devrai-je faire quelque chose de spécial pour un fichier encodé en UTF-8?

Enfin, une solution Groovy serait également utile.

Était-ce utile?

La solution

Vous devriez utiliser Text :: CSV_XS au lieu de le faire vous-même. Il prend en charge les nouvelles lignes incorporées dans les enregistrements ainsi que les fichiers Unicode. Vous devez spécifier les bonnes options lors de la création de l'analyseur. Veillez donc à lire attentivement la documentation.

Autres conseils

Cela fonctionne pour moi:

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

Voici une version groovy. Selon les besoins, il est possible que certaines nuances ne soient pas comprises (par exemple, des chaînes entre guillemets pouvant contenir des virgules). Il faudra également apporter des modifications si la nouvelle ligne peut se produire au milieu du champ plutôt que toujours à la fin.

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

Cela pourrait être trop simple (ou ne pas gérer assez bien le cas général),

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

émet;

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

C’est principalement en réponse à votre question sur le codage UTF-8.

En fonction de l'encodage spécifique, vous pouvez également avoir besoin de rechercher des octets nuls. Si le conseil ci-dessus n'a pas fonctionné pour vous, remplacer 's / \ n, /, / g' par 's / \ c @? \ N (\ c @ ?,) / $ 1 / g' peut fonctionner sans casser l'encodage , bien qu’il soit peut-être plus prudent de le faire de manière itérative (appliquez '/ s \ c @? \ n (\ c @ ?,)) / $ 1 /' à chaque ligne au lieu de les concaténer et de les appliquer globalement). C’est vraiment un hack, pas un substitut du support unicode réel, mais si vous avez juste besoin d’une solution rapide, ou si vous avez des garanties concernant l’encodage, cela pourrait vous aider.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top