Sur mon cygwin, j'ai aussi des fichiers de mon répertoire local qui sont listés... :calim2:
Version imprimable
Sur mon cygwin, j'ai aussi des fichiers de mon répertoire local qui sont listés... :calim2:
Normal, puisque le répertoire local fait normalement partie du tableau @INC.
On peut filtrer les résultats:
Ou supprimer temporairement le répertoire courant (".") de @INC:Code:perl -M5.10.1 -e "sub search {for $d (glob qq|$_[0]/*|) { -d $d ? search ($d) : say $d if $d =~ /\.pm/;}} search ($_) for (@INC)"
Code:perl -M5.10.1 -e "pop @INC; sub search {for $d (glob qq|$_[0]/*|) { -d $d ? search ($d) : say $d if $d =~ /\.pm/;}} search ($_) for (@INC)"
Hello à tous,
suite à une fausse manipulation avec sed sur des fichiers type csv, je me suis retrouvé avec tout un répertoire comportant mes fichiers avec chaque élément sur une seule ligne :aie:
Exemple avant sed:
Après sed:Code:
1
2
3 col1|col2|col3 a1|a2|a3 b1|b2|b3
Evidemment, pas de sauvegarde des fichiers :cry: et pas trop envie de les refaire tous :?Code:
1
2
3
4
5
6
7
8
9 col1 col2 col3 a1 a2 a3 b1 b2 b3
D'où mon uniligne du jour (merci perl ;)) : comment, à partir d'un fichier texte, créer un fichier type csv en utilisant chaque ligne pour remplir les "cellules" à la suite les unes des autres sur un nombre de colonnes bien défini ?
Par exemple, pour un csv de x colonnes, la lecture du fichier texte va donner :
première ligne du fichier > premier champ, première ligne du csv
deuxième ligne du fichier > deuxième champ, première ligne du csv
x ième ligne du fichier > x ième champ, première ligne du csv
x+1 ième ligne du fichier > premier champ, deuxième ligne du csv
etc.
-i.bak écrit dans le fichier ouvert en le remplaçant (et en sauvegardant l'original avec l'extension .bak)Code:perl -i.bak -e "while (<>) {chomp;print;print $.%6?'|':qq|\n|}" <fichier>
chomp supprime le caractère de fin de ligne de l'élément lu
print écrit l'élément lu dans le fichier grâce au paramètre -i
print $.%6?'|':qq|\n| écrit soit un pipe (séparateur de mes champs dans le csv cible) soit un saut de ligne si on a atteint la fin de la ligne
$.%6 regarde si la ligne courante ($.) est un multiple de 6; c'est ce qui permet de savoir si on doit écrire un pipe pour séparer deux éléments ou terminer la ligne lorsque le nombre d'éléments sur la ligne est atteint
rappel:
...?...:... opérateur ternaire équivalent à if ... then ... else ...
qq|...| permet d'éviter l'utilisation des " parfois problématiques sous Windows ou dans les alias. Cette commande est équivalente à "..."
Avec le "6" qui correspond au nombre de colonnes du fichier cible et le '|' qui est le séparateur.
Exemple concret :
Pour info, sous Windows, je l'ai passé comme ça:Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 D:\>cat test col1 col2 col3 a1 a2 a3 b1 b2 b3 D:\>perl -i.bak -e "while (<>) {chomp;print;print $.%3?'|':qq|\n|}" test D:\>cat test col1|col2|col3 a1|a2|a3 b1|b2|b3
a+Code:FOR %A IN (*.txt) DO perl -i.bak -e "while (<>) {chomp;print;print $.%6?'|':qq|\n|}" %A
Bonjour,
Juste pour information, faisable sous paste:
Code:
1
2
3
4
5
6
7
8
9
10 $ cat text1.txt col1 col2 col3 a1 a2 a3 b1 b2 b3
Mais c'est toujours bon à prendre sous perl :ccool:Code:
1
2
3
4$ paste -d'|' - - - <text1.txt col1|col2|col3 a1|a2|a3 b1|b2|b3
Encore plus court :
(cygwin/linux)Code:perl -i.bak -nE 'chomp;print $_, $.%3 ? "|":"\n"' *.txt
L'option -n fait la while(<>) toute seule.
La commande paste existe sous Unix/Linux, mais peut-être pas sous les autres OS.
Sinon, l'option -n de la ligne de commande Perl permet de simplifier la rédaction d'un uniligne en ajoutant une boucle "while <>" implicite.
peut aussi s'écrire:Code:perl -i.bak -e "while (<>) {chomp;print;print $.%3?'|':qq|\n|}" test
L'option -p est également intéressante à connaître (mais pas utilisable ici), elle ajoute un print implicite. Par exemple:Code:perl -ni.bak -e "chomp;print;print $.%3?'|':qq|\n|" test
peut se réécrire plus brièvement:Code:perl -e "while (<>) {s/toto/titi/g; print};" fic.txt
EDIT: Oups, je n'avais pas vu le message de Philou qui disait la même chose.Code:perl -pe "s/toto/titi/g;" fic.txt
Une autre façon de faire:
On peut d'ailleurs se passer du g puisqu'un seul remplacement par ligne,donc:Code:perl -pe '$.%3 && s/\n/|/g' text1.txt
ou via un yank:Code:perl -pe '$.%3 && s/\n/|/' text1.txt
Code:perl -pe '$.%3 && y/\n/|/' text1.txt
Suite à cette discussion :
Q/R : Comment ajouter du contenu fixe en début ou en fin de fichier
Chapitres : Traitement de fichiers
Testé sous : Linux, Windows (ActiveState Perl, Strawberry Perl)
Code:perl -i.bak -ne 'if ($lastARGV ne $ARGV) { print "ceci est un entête\n"; $lastARGV = $ARGV} print; print "ceci est un pied\n" if eof' test1.dat test2.dat ...
Afin de ne pas se perdre dans les posts et surtout dans le but que les commentaires soient liés uniquement à une seule Q/R, je vous recommande de faire vos propositions dans le sous-forum contribuez.
Pour une meilleure lisibilité, mettez en titire le tag [UNILIGNE].
Exemple :
[UNILIGNE] Comment ajouter du contenu fixe en début ou en fin de fichier
Chapitres : Traitement de fichiers
Testé sous : Linux, Windows (ActiveState Perl, Strawberry Perl)
Si je constate que nous disposons de beaucoup de propositions, je ferais une FAQ dédiée.Code:perl -i.bak -ne 'if ($lastARGV ne $ARGV) { print "ceci est un entête\n"; $lastARGV = $ARGV} print; print "ceci est un pied\n" if eof' test1.dat test2.dat ...
Suite à cette discussion:
pour constituer une grille Euromillions on doit choisir 5 nombres entre 1 et 49 et 2 "étoiles" entre 1 et 11. Perl à la rescousse :
Code:
1
2
3
4 Taisha:~/perl/forum $ perl -E 'for ([5, 49], [2, 11]) { my %h; ++$h{1 + int(rand($_->[1]))} while keys %h != $_->[0]; say "@{[keys %h]}"}' 26 32 15 28 35 11 4 Taisha:~/perl/forum $
Je n'ose pas imaginer ce qu'il se passerait si ton tirage devenait gagnant :mrgreen:
Mise à jour faite de la question Euromillions :mrgreen:, sans modifier le tirage :aie: !
N.B. 10 ans après, on ne sait jamais.