J'essaie de balayer certaines listes dans un fichier CSV correctement formaté pour l'importation de base de données.
Mon fichier de départ ressemble à ceci avec ce qui est supposé être chaque "ligne" couvrant plusieurs lignes comme ci-dessous
Mr. John Doe
Exclusively Stuff, 186
Caravelle Drive, Ponte Vedra
33487.
J'ai créé un script sed
qui nettoie le fichier (il y a beaucoup de mises en forme "sales" comme les doubles espaces et les espaces avant/après les virgules). Le problème est le zip avec la période. Je voudrais changer cette période pour une nouvelle ligne, mais je ne parviens pas à la faire fonctionner.
La commande que j'utilise est la suivante:
sed -E -f scrub.sed test.txt
et le scrub.sed
Le script est le suivant:
:a
N
s|[[:space:]][[:space:]]| |g
s|,[[:space:]]|,|g
s|[[:space:]],|,|g
s|\n| |g
s|[[:space:]]([0-9]{5})\.|,FL,\1\n |g
$!ba
Ce que je reçois c'est
Mr. John Doe,Exclusively Stuff,186 Caravelle Drive,Ponte Vedra,FL,33487n
Si figuré que le Zip +. (Point) serait un grand "délimiteur" pour utiliser la substitution sur et pendant que je peux le trouver, je ne peux pas sembler lui dire de mettre une nouvelle ligne.
La plupart des choses que j'ai trouvées en ligne concernent le remplacement de la nouvelle ligne par quelque chose d'autre (généralement leur suppression), mais pas grand chose sur le remplacement par une nouvelle ligne. J'ai trouvé ceci, mais cela n'a pas fonctionné: Comment insérer un caractère de nouvelle ligne après une virgule dans `), (` avec sed?
Y a-t-il quelque chose qui me manque?
Mise à jour:
J'ai édité mon fichier scrub.sed en insérant la nouvelle ligne littérale. Ça ne marche toujours pas
:a
N
s|[[:space:]][[:space:]]| |g
s|,[[:space:]]|,|g
s|[[:space:]],|,|g
s|\n| |g
s|[[:space:]]([0-9]{5})\.|,FL,\1\
|g
$!ba
Ce que je reçois est (tout sur une seule ligne):
Mr. John Doe,Exclusively Stuff,186 Caravelle Drive,Ponte Vedra,FL,33487 Mrs. Jane Smith,Props and Stuff,123 Main Drive,Jacksonville,FL,336907
Ma sortie attendue devrait être:
Mr. John Doe,Exclusively Stuff,186 Caravelle Drive,Ponte Vedra,FL,33487
Mrs. Jane Smith,Props and Stuff,123 Main Drive,Jacksonville,FL,336907
Le sed
sur BSD ne supporte pas le \n
représentation d'une nouvelle ligne (en la transformant en un littéral n
):
$ echo "123." | sed -E 's/([[:digit:]]*)\./\1\n next line/'
123n next line
GNU sed
supporte le \n
représentation:
$ echo "123." | gsed -E 's/([[:digit:]]*)\./\1\nnext line/'
123
next line
Les alternatives sont:
Utilisez un séparateur de caractères que vous utiliserez ensuite tr
traduire en une nouvelle ligne:
$ echo "123." | sed -E 's/([[:digit:]]*)\./\1|next line/' | tr '|' '\n'
123
next line
Ou utilisez une nouvelle ligne littérale échappée dans votre script sed:
$ echo "123." | sed -E 's/([[:digit:]]*)\./\1\
next line/'
123
next line
Ou utilisez awk
:
$ echo "123." | awk '/^[[:digit:]]+\./{sub(/\./,"\nnext line")} 1'
123
next line
Ou utilisez GNU sed qui supporte \n
La méthode portable pour obtenir une nouvelle ligne dans sed est une barre oblique inverse suivie d'une nouvelle ligne:
$ echo 'foo' | sed 's/foo/foo\
bar/'
foo
bar
Je vous garantis qu'il existe une solution beaucoup plus simple à votre problème en utilisant awk plutôt que sed.
Ce qui suit fonctionne sur Oracle Linux, x8664:
$ echo 'foobar' | sed 's/foo/foo\n/'
foo
bar
Si vous avez besoin de faire correspondre plus d'une fois par ligne, vous devrez placer un g
à la fin, comme dans:
$ echo 'foobarfoobaz' | sed 's/foo/foo\n/g'
foo
barfoo
baz