fusionner les lignes csv si elles ne se terminent pas par un tube

J’ai un fichier csv plutôt volumineux où chaque ligne doit se terminer par un tube (|) et si elle ne combine pas la ligne suivante avant de retrouver un tube. Cela doit être fait en utilisant un script shell.

J’ai une réponse comme

awk '!/|$/{l=l""$0|next|}{print l""$0|l=""}' file 

Mais cela me donne une erreur car la taille de chaque ligne est assez grande pour moi. J’ai découvert que je devais utiliser perl pour faire cela et avoir essayé quelque chose comme ci-dessous mais cela produit le résultat souhaité.

 perl -pe 's/^\n(|\n)/ /gs' input.csv > output.csv 

Mes données ressemblent à

 A|1|abc|| |2|def|hello world| |3|ghi|| 

Et le résultat souhaité devrait être

 A|1|abc|| |2|def|hello world| |3|ghi|| 

De toute évidence, la taille de la ligne est assez grande par rapport à l’échantillon ici.

Toute aide serait très appréciée.

Cela devrait fonctionner:

 perl -lne 'unless(/\|$/){$line=$line.$_}else{print $line." $_";undef $line}' your_file 

Si vous voulez faire un remplacement in-situ, faites ceci:

 perl -i -lne 'unless(/\|$/){$line=$line.$_}else{print $line." $_";undef $line}' your_file 

vérifiez ici votre commentaire

 awk '{printf "%s",$0} /[|][[:space:]]*$/ {print ""}' 

Imprimer chaque ligne sans nouvelle ligne. Si le dernier caractère non blanc est un tube, vous avez une ligne complète, donc imprimez une nouvelle ligne.

Cela devrait heureusement gérer tous les cas pour vous, et ne pas casser sur une longueur de ligne:

 #!/bin/bash newLine=0 IFS= while read -r -n 1 char; do if [[ $char =~ ^$ ]]; then if [[ $newLine -eq 1 ]]; then newLine=0 echo '|' # add a newline fi elif [[ $char =~ . && ( $newLine -eq 1 ) ]]; then newLine=0 echo -n "|$char" elif [[ $char =~ [|] ]]; then if [[ $newLine -eq 1 ]]; then echo -n '|' fi newLine=1 else echo -n $char fi done < file.txt 

S'il vous plaît noter que la construction d'un lexer à la main en bash est généralement une mauvaise idée.