colzat

alain Adelmar
                                                                          aadelmar@numericable.fr beuuh c est quoi ca

Ce script permet de modifier (permuter ou ôter) les colonnes d'un fichier.  Il fonctionne avec les fichiers qui ont des colonne formater (ayant des colonnes
d'égales nombre de caractères) mais aussi avec des colonnes pas formater.
Dans ce second cas il effectue le trie suivant les blancs qui séparent les colonnes,
Troisième cas: Il peut aussi définir des colonnes suivant le nombre de caractères que vous lui donnerai,  je pense faire aussi une autre option permettant d'entrer un motif, permettant de couper les colonnes. Il est très pratique.
Il accepte plusieurs options et le nom du fichier à traiter en guise d'argument. Le fichier de sortie aussi, pour plus d'ample info sur ce script, lire la doc à la fin
du script.  Je me le suis fait pour travailler des gros fichier (dictionnaires de traduction anglais-français et il tiens la route sur des colonnes de plusieurs dizaines de milliers d'enregistrement).
le script ici et la page d'explication ici



code (à copier et coller sur un fichier en l'appelant colzat.pl, puis le rendre exécutable (chmod +x colzat.pl)):

#!/usr/bin/perl -w
# remd: colzat est un script écrit pour modifier des listes, du texte.         *
# Il envisagera le fichier à modifier comme si c'etait une liste formatée.     *
# Deux options pour séléctionner soit de caractères soit des mots: (-c et -m)  *
# --------------------                                                         *
# Usage: colzat [-c|m] [n|n-n[1-9]] [source] [cible|-cible]                    *
#                                                                              *
#      -c  pour caractère, séléctionnera n caractère sur chaque ligne, créant  *
#          virtuellement une colone sur chaque ligne qu'il déplacera (par def) *
#          à la fin de chaque ligne vers un fichier cible (voir 3éme argument).*
#          Ou carrement dans le fichier d'echantillon (f-sup) si  vous l'avez  *
#          demander dans la ligne de commande.   Vous pouvez aussi créer une   *
#          fourchette, exemple: 3-8 qui séléctionnera du 3éme car au 8éme car. *
#                                                                              *
#      -m  pour mot, séléctionnera n mot sur chaque ligne, même principe qu'au *
#          dessus. Les mots sont calculés en fonction des espaces.Il peut aussi*
#          en plaçant deux chiffres entre un tiré, faire une sélection du mot n*
#          au mot n (voir au dessous).                                         *
#                                                                              *
#       n  pour chiffre, si un seul chiffre est entrer comme argument, en tant *
#          que -c (caractère) ou -m (mot), la sélection s'éfféctuera depuis le *
#          debut de la ligne. Pour une sélection à l'interieur de la ligne il  *
#          faudra indiquer le chiffre du debut de la sélection suivi d'un tiret*
#          suivi du chiffre de fin de sélection (sans espace entre). Exemple:  *
#          2-4        # qui créera la colone comprise entre le 2éme et le 4éme.*
#          La ligne demarre au 1er mot et donc pas a zero, pour pas ce tromper *
#          pensez à ajouter mentalement éme, donc 2-4 = 2éme au 4éme           *
#                                                                              *
#  source  qui indique le fichier à traiter. Entrer le chemin complet si il ne *
#          se trouve pas dans le répertoire courant.                           *
#                                                                              *
#   cible  qui sera créé et recevra les modifications faites au fichier source.*
#          C-a-d: la selection sera placer en fin de ligne. Exemple:           *
#       (avec la commande: colzat.pl -m 3-5 list.txt slist.txt              *
#          le texte de list.txt:                                               *
#              je suis fou du chocolat lanvin                                  *
#              tu as un bon systeme linux                                      *
#          ce transformera sur slist (la cible) en:                            *
#              je suis Lanvin fou de chocolat                                  *
#              tu as linux un bon systeme                                      *
#          Par mesure de prudence, le fichier source reste inchangé.           *
#                                                                              *
#  -cible  pour créé un fichier qui ne recevra que la selection, pour ceux qui *
#          ne veulent que la colonne voulue ou en vue de faire d'autres modifs.*
#          Exemple sur la commande: colzat.pl -m 3-5 list.txt -slist           *
#          le fichier -cible(-slist.txt) recevra (du même fichier list.txt)    *
#              fou du chocolat                                                 *
#           un bon systeme                                                  *
#          Le fait de placer un tiret devant le nom de la cible fait qu'il ne  *
#          recoit que la selection.                                            *
#------------------------------------------------------------------------------*
# En gros j'ai écrit ce script pour palier au contrôle déjà present sur les    *
# éditeurs, il permet de prendre ou bouger des colonnes et de les faire passer *
# de devant à derrière. Ou juste de sélectionner les colonnes que l'on à besoin*
# J'éspère que vous comprendrai ce qu'il peut faire (je sais je suis pas clair)*
# et qu'il vous servira autant qu'il me sert. Il fonctionne bien.              *
# écrit par Alain Adelmar le 21 avril 2010 à Pessac 33600 Gironde France       *
#------------------------------------------------------------------------------*
$ID$

use strict;

# use warnings;
use Cwd;
my $dir= cwd;

# traitement du temps pour date et heure en français
(my $sec,my $min,my $heure,my $mjour,my $mois,my $annee,my $sjour,my $ajour,my $isdst) =  localtime(time);
my @lssjour = qw( Dim Lun Mar Mer Jeu Ven Sam);
my @lssmois = qw ( Janvier Fevrier Mars Avril Mai Juin Juillet Aout Septembre Octobre Novembre Decembre );

my $french_date_now = "$lssjour[$sjour] $mjour $lssmois[$mois] " . ($annee+=1900) . " - $heure:$min:$sec";


my $lx = "x" x 20;
my $argv = my $argm = my $file = my $fout = my $resp = my $f_sup = my $rootfile = my $pathf = "";
my $moi = "alain Adelmar";
my $recap_lbl= "$0 écrit par $moi \nle 21 Avril 2010\nexecuter le $french_date_now\n";
my $mode = "change";
my $datenum = my $deb = my $fin = my $k = my $u = my $args = 0;
my @primcol = my @sel = my @reste = my @nwcontenu = my @car = my @mot = my @ls_argv = "";
my $lsel = my $lreste = my $lprimcol = my $nl = "";
print "$lx\n$recap_lbl";

# pour l'adressage/les systeme UNIX, Linux, cygwin ou autre (/) et ceux de M$ (\)
my @gnul = ( "\\", "\/");   #pas mal because $gnul[$gnus] sera toujours bon, je suis trop fort
my $gnus = 0;
my $cong= "this is a real gnu OS, congratulation\n";
if ($^O =~ /[msys|cygwin|linux]$/) {
  $gnus++;
  print "$cong";
  }
elsif ($dir =~ /\//) {
  $gnus++;
  print "$cong";
  }
else {
  print "Vous etes sur une machine Petite et Molle (MicroSoft), beuuurk...\n";
  print "enfin quoi, sur un OS de merde\n";
  print "gnus ne vaut que $gnus, et en plus, vos fichiers sont du style:\n";
  print "C:" . "$gnul[$gnus]" . "caca" . "$gnul[$gnus]boudin au lieu de /super/extra\n os: $^O \n";
  print "Mais $0 fonctionnera tout de meme sur cette grosse chiote de systeme\n";
  }
my $slash = $gnul[$gnus];



#----------------- sortie formatée pour l'affichage fichiers/sorti ---------
format STDOUT_TOP =
Page @<<
$%

 n       ligne                    
=== ===========================================================
.


# traitement arguments - fichier a traiter et verif validité

if (@ARGV) {
  @ls_argv = "@ARGV";
  if ($ARGV[0] =~ /^-/) {
    $ARGV[0] =~ s/-(\w+)/$1/;
    $argm = $ARGV[0];   # assigne $argv  
#    ($argv = "b") if ($ARGV[0]=~ /^b/);   # pour b pour binaire
#    ($argv = "u") if ($ARGV[0]=~ /^u/);   # pour usage
#    ($argv = "l") if ($ARGV[0]=~ /^l/);   # pour latin1 => utf8
#    ($argv = "o") if ($ARGV[0]=~ /^o/);   # pour output (c.a.d: fichier differant)
    }
  else {
    &use_and_expl;
    print "Ici il manque le mode de sélection -c ou -m (par caracteres ou par mots), par defaut c'est le nombre de caractère(s)\n";
    }
  if($ARGV[1] =~ /^\d/) {
    # receuillir $ARGV[1]
    #($deb = $1, $fin = $2)= split(/-/, $ARGV[1]);
    $fin = undef;
    ($deb = $1, $fin = $2)= split(/-/, $ARGV[1]);
    # si l'utilisateur n'a pas entrer de selection de debut, completer son choix
    if(undef $fin) {
      $fin = $deb;
      $deb = 0;
      }
    #if($ARGV[1] =~ /^\d[^-]/) {
    #  $argc = $ARGV[1];
    #  }
    $file = $ARGV[2];
    &veriff;
    $fout = $ARGV[3];
    &verif_fout;
    ($args++) if ($ARGV[3]=~ /^-/);
    #($deb = $1, $fin = $2) if ($ARGV[1]=~ /^(\d)-(\d?)/);
    
    }
  else {
    &use_and_expl;
    print "Ici il manque le chiffre representant le(s) caractère(s) permettant la selection de la colonne\n";
    die "navré $!";
    }
  }
else {
  &use_and_expl;
    print "Ici il manque tout, man ./colzat\n";
    }

# ouverture du fichier en lecture seule
open F, "$file" or die "ouverture de $file impossible $!";
#if ($argv =~ /b/) {
#    binmode F;
#}
my @contenu = <F>;
close F || die "Fermeture de $file impossible $!";

#----------------------------ici c'est bien -------------------
my $i = 0;
$deb -= 1;
$fin -= 1;

foreach my $l(@contenu) {
  chomp $l;
  if($argm eq "m") {
    # coupe la ligne en mots
    (@mot) = split(/ /, $l);
    #placer dans $1, $2 et $3 les colonnes @primcol, @sel, @reste
    &decoupeligne2mot;
    $lprimcol = join("", @primcol);
    $lsel = join("", @sel);
    $lreste = join("", @reste);
    if($args == 0) {
      $nl = "$lprimcol$lreste$lsel";
      push @nwcontenu, "$nl\n";
      }
    # sinon pousse juste la ligne dans @nwcontenu
    else {
      push @nwcontenu, "$lsel\n";
      }
    @primcol = @reste = @sel = "";
    $lprimcol = $lreste = $lsel = "";
    }
  else {
    (@car) = split(//, $l);
    
    &decoupeligne2car;
    $lprimcol = join("", @primcol);
    $lsel = join("", @sel);
    $lreste = join("", @reste);
    if($args == 0) {
      $nl = "$lprimcol$lreste$lsel";
      push @nwcontenu, "$nl\n";
      }
    # sinon pousse juste la ligne dans @nwcontenu
    else {
      push @nwcontenu, "$lsel\n";
      
      }
    @primcol = @reste = @sel = "";
    $lprimcol = $lreste = $lsel = "";
    }
  write;
  $k++;
  }

open FOUT, ">$fout" or die "Ouverture de $fout impossible $!";
print FOUT "$lx\n$recap_lbl\ncommande: @ls_argv\n$lx\n";
print FOUT @nwcontenu;
close FOUT || die "Fermeture de $fout impossible $!";

      

#--------------------------------------------------------------
# attention par mot et par car pas exactement pareil
sub decoupeligne2car {
 
  my $i = 0;
 
  foreach my $c(@car) {

    if($i < $deb) {
      push @primcol, $c;
      }
    elsif($i < $fin) {
      push @sel, $c;
      }
    else {
      push @reste, $c;
      }
    $i++;
    }
  }

sub decoupeligne2mot {

  my $i = 0;
   
  foreach (@mot) {
    if($i < $deb) {
      push @primcol, "$mot[$i] ";
      }
    elsif($i < $fin) {
      push @sel, "$mot[$i] ";
      }
    else {
      push @reste, "$mot[$i] ";
      }
    $i++;
    }
  }


sub veriff {
 
  unless (-f $file) {
    print "Donner le nom du fichier ou vous desirez selectionner une colone\n";
    chomp($file = <STDIN>);
    if (-f $file) {
      print "ok pour $file on continu\n";
      }
    else {
      print "pas possible $file n est pas un nom de fichier valide\n";
      die "desole il faut refaire, avec les bonnes valeurs\n";
      }
    }

  if ($file !~ /$slash/) {
    $rootfile = $file;
    $file = "$dir$slash$file";
  }
  else {
    $rootfile = $file;
    (my @pathf) = split("$slash", $rootfile);
    $rootfile = pop @pathf;
  }
  while (!(-f $file)) {
    print "Veuillez entrer un nom de fichier, et son path si ailleur que dans le $dir:\n";
    chomp ($file = <STDIN>);
  }
  my $fr_date_file = &datefile($mode);
  print "info sur fichier source: $file\t$fr_date_file\n";
}


sub datefile {
 
  ($mode = 8) if ($mode=~ /^a/);
  ($mode = 9) if ($mode=~ /^m/);
  ($mode = 10) if ($mode=~ /^c/);
  #print "mode vaut : $mode\n";
  $datenum = ((stat($file))[$mode]);
  #print "$datenum\n";
  (my $sec,my $min,my $heure,my $mjour,my $mois,my $annee,my $sjour,my $ajour,my $isdst) =  (localtime($datenum));
  my $fr_date_file = "$lssjour[$sjour] $mjour $lssmois[$mois] " . ($annee+=1900) . " - $heure:$min:$sec";
  return $fr_date_file;
}

sub use_and_expl {
  print "$lx\nUsage: colzat.pl [-cm] [source] [cible|-f_sub]\n" .
    "exemple: colzat.pl -c 8 /home/alain/ma_liste.csv -col1_ls.txt\nou\n" .
    "\tcolzat.pl -m 2-4 ma_liste.csv sortie_ma_liste.csv\n$lx\n\n";
  }



sub verif_fout {

  if ($fout eq "") {
    if ($args == 0) {
      print "Donner un nom au fichier de sortie ou taper juste sur [Enter]\n" .
      "pour avoir un nom par defaut comme: sorti_$file\n";
      }
    elsif ($args >= 1) {
      print "Donner un nom au fichier qui recevra votre colonne ou taper juste sur [Enter]\n" .
      "pour avoir un nom par defaut comme: sorti_$file\n";
      }
    chomp($fout = <STDIN>);
    if ($fout eq "") {
      $fout = "$dir$slash" . "sorti$u" . "_$rootfile";
      }
    }

  $u= 0;
  while (-e $fout) {
    $u++;
    $fout = "$dir$slash" . "sorti$u" . "_$rootfile";
  }
  print "info fichier de sortie:  $fout\t$french_date_now\n$lx\n";
}

format STDOUT =
@|||  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$k, $nl
.

#END;




1;


=head1 NOM

  B<colzat.pl> - deplace des colonnes de caractères ou de mot sur la totalité
  ou une partie d'un fichier, du debut ou à l'interieur d'une ligne vers la fin
  de la ligne ou dans un fichier I<f-sup>.  

=head1 SYNTAXE
 
  B<colzat.pl> [B<-cm>] [B<n>|B<n-n>] [F<source>] [B<->F<cible>÷]
 
  par defaut:
  B<colzat.pl> [B<n>] [F<source>]

=head1 DESCRIPTION
 
  Ce script E<&agrave;> pour vocation de deplacer une colonne de caracteres,
  du debut de chaque ligne vers la fin de chaque ligne (B<n> represantant le
  nombre de caracteres formant la largeur de la colonne).  Il peut le faire
  egalement (avec l'option n-n) du caractere n au caractere n.
  Par défaut c'est le nombre de caracteres qui definit sa largeur, mais il
  lui est possible avec l'option B<-m> de le faire avec des mots, comme pour
  les caracteres, il pourra selectionner la colonne soit depuis le debut de
  la ligne (par defaut) soit avec B<n-n> du B<n>ieme mot au B<n>ieme mot.
  Le fichier de sortie recevra la modification (ce script ne touche pas au
  fichier source par mesure de securite). Si vous ne desirez recevoir que la
  colonne selectionner placer simplement un tiret devant le nom du fichier
  cible/sortie.

=head1 OPTIONS
 
  -c  pour caracteres, qui est facultatif car par defaut c'est le nombre de
      caracteres qui est applique.
  -m  pour mot, donc le chiffre ou les chiffres separé d'un tiret represen-
      terons le nombre de mot de la colonne selectionnee. (la selection de
      mot ce fait par un eclatement de la ligne par les espaces).
      I<Donc eviter les textes ou listes commençant par des espaces>.

  n n-n  Un seul chiffre represente une selection depuis le debut de la
      ligne, deux chiffre séparer d'un tiret (sans espace) represente une
      selection du nieme car ou mot au nieme car ou mot.

  source  Nom du fichier ou vous desirer faire une selection. nom complet
      si pas de le repertoire courant.

  cible  Nom du fichier ou vous désirez recevoir la modification. Comme
      pour le source indiquer le nom complet si en dehors du repertoire
      courrant. C'est le fichier de sortie.

  -cible idem mais le pêtit tiret devant signifi qu'il ne veut que la
      selection et pas le reste du texte.

=item Exemple:
      
      pour un texte de ce type:
      je suis fou du chocolat Lanvin
      tu as un bon systeme Linux
      
      donnera avec la commande: colzat.pl -m 3-5 list.txt sortie_ls.log

      je suis Lanvin fou du chocolat
      tu as Linux un bon système

=head1 AUTEUR

      Adelmar Alain
      6 rue de Tunis, 33600 Pessac
      email: aadelmar@numericable.fr
      http://perso.numericable.fr/aadelmar/
      num de version: 1.2
      fait le: Mardi 22 Juin 2010

=cut


et voilà.
Il faut l'utiliser, le tester, ce le perfectionné.