web-dev-qa-db-fra.com

J'ai besoin d'utiliser sed / awk pour obtenir la sortie souhaitée

Order:479959,60=20130624-09:45:02.046|35=D|11=884|38=723|21=1|1=30532|10=085|59=0|114=Y|56=MBT|40=1|43=Y|100=MBTX|55=/GCQ3|49=11342|54=1|8=FIX.4.4|34=388|553=2453|9=205|52=20130624-09:45:02.046|

Order:24780,100=MBTX|43=Y|40=1|34=388|553=2453|52=2013062409:45:02.046|9=205|49=11342|54=1|8=FIX.4.4|55=/GCQ3|11=405|35=D|60=20130624-09:45:02.046|56=MBT|59=0|114=Y|10=085|21=1|38=470|1=30532|

Order:799794,55=/GCQ3|49=11342|54=1|8=FIX.4.4|34=388|553=2453|9=205|52=2013062409:45:02.046|40=1|43=Y|100=MBTX|38=350|21=1|1=30532|10=085|59=0|114=Y|56=MBT|60=20130624-09:45:02.046|35=D|11=216|

Order:72896,11=735|35=D|60=2013062409:45:02.046|56=MBT|59=0|114=Y|10=085|1=30532|38=17|21=1|100=MBTX|43=Y|40=1|553=2453|9=205|52=20130624-09:45:02.046|34=388|8=FIX.4.4|54=1|49=11342|55=/GCQ3|

Je veux obtenir le numéro après 38= et le nombre après 11= qui devrait être renommé Clientid

La sortie doit être: -

Orderid-479959 38= 723 Clientid=884
Orderid-24780 38= 470 Clientid=405
Orderid-799794 38= 350 Clientid=216
Orderid-72896 38= 17 Clientid=735

Toute aide serait appréciée.

4
Sonal

Vous pouvez utiliser

sed -nr 's/Order:([0-9]+),.*[,\|]38=([0-9]+)[,\|].*/Orderid-\1 38= \2/p' file | tee file2

Alors

sed -nr 's/.*[,\|]11=([0-9]+)[,\|].*/Clientid=\1/p' file | tee file3

Alors

paste -d ' ' file2 file3

Vous obtenez votre sortie sur stdout - redirigez à votre guise.

Je ne peux pas l'avoir sur une seule ligne (bien que quelqu'un peut évidemment ) puisque le 11= et 38= les champs peuvent être dans l'un ou l'autre ordre - je dois lire le fichier deux fois. Vous pouvez l'intégrer dans un script comme celui-ci:

#!/bin/bash
sed -nr 's/Order:([0-9]+),.*[,\|]38=([0-9]+)[,\|].*/Orderid-\1 38= \2/p' "$1" > file2
sed -nr 's/.*[,\|]11=([0-9]+)[,\|].*/Clientid=\1/p' "$1" > file3
paste -d ' ' file2 file3 > outfile
rm file2 file3

(cela nettoie les fichiers que nous écrivons dans le processus et écrit la sortie finale dans un fichier outfile)

Usage:

  • collez le script dans un fichier vide et enregistrez-le
  • donnez-lui la permission d'exécuter: chmod u+x script
  • exécutez-le avec le nom de votre fichier d'entrée comme argument: ./script file
  • changement file2 et file3 dans le script si vous avez des fichiers existants avec ces noms dans le répertoire courant!

Explication

  • s/old/new remplacez old par new
  • -r utiliser ERE
  • -n n'imprime pas tant que nous ne le demandons pas (cela va simplement supprimer les lignes vides)
  • [,\|] rencontre , OR littéral |
  • ([0-9]+) quelques chiffres à sauvegarder pour plus tard
  • \1 référence arrière au modèle enregistré
  • tee écrivez dans un fichier et imprimez sur stdout aussi pour pouvoir le vérifier
  • > somefile redirige la sortie vers somefile au lieu de stdout
  • paste -d ' ' file2 file3 collez les colonnes du fichier3 après les colonnes du fichier2 en utilisant un espace comme délimiteur.
  • rm file2 file3 supprimer le fichier2 et le fichier3
4
Zanna

Un liners n'est pas toujours sympa:

$ sed 's/[|,]\(11=[^|]*\).*\(|38=[^|]*|\).*/\2\1|/; s/Order:\([0-9]*\).*|38=\([0-9]*\).*|11=\([0-9]*\)|.*/Orderid-\1 38= \2 Clientid=\3/' foo
Orderid-479959 38= 723 Clientid=884
Orderid-24780 38= 470 Clientid=405
Orderid-799794 38= 350 Clientid=216
Orderid-72896 38= 17 Clientid=735

Explication

  • s/old/new/ Remplacez old par new
  • [|,] Correspond à | Ou ,
  • \(11=[^|]*\) correspond à n'importe quel nombre de caractères sauf | après 11= et enregistre 11=whatever pour une utilisation ultérieure sous \1
  • .* N'importe quel nombre de caractères
  • \(|38=[^|]*|\) enregistrer |38=whatever| pour une utilisation ultérieure sous \2
  • \2\1| Rétro-références en remplacement (cela rend les champs cohérents afin que nous puissions les traiter dans la prochaine commande)
  • ; Sépare les commandes, comme dans le Shell
  • Order:\([0-9]*\).*|38=\([0-9]*\).*|11=\([0-9]*\)|.* correspond à ce modèle (maintenant nous l'avons nettoyé) en enregistrant à nouveau les pièces que nous voulons réutiliser dans \(parentheses\)
  • Remplacement de Orderid-\1 38= \2 Clientid=\3 Par \1\2 Et \3 Renvois aux numéros que nous avons enregistrés avec \(\)
3
muru

Solution Perl:

En une ligne:

Perl -a -F'[:|,]' -lne  'next if $_ =~ /^$/;printf("%sid-%s ",$F[0],$F[1]);foreach(@F){$t=$_ if $_ =~ "38=";$id=$_ if $_ =~ "11="};$id =~s/11=//;printf("%s Clientid=%s\n",$t,$id)' input.txt

Ou comme script:

#!/usr/bin/env Perl
use strict;
use warnings;

open(my $fh,'<',$ARGV[0]) or die $!;

while(my $line = <$fh>){
    next if $line =~ /^$/;
    my @words  = split /[:|,]/,$line;
    printf("%sid-%s ",$words[0],$words[1]);
    my $t;
    my $id;
    foreach my $Word (@words){
        $t = $Word if $Word =~ "38=";
        $id=$Word if     $Word =~ "11=";
        $id =~ s/11=// if length($id);
    }
    printf("%s Clientid=%s\n", $t ,$id);
}
close($fh) or die $!;

Résultats de test:

$ ./parse_orders.pl ./input.txt                                                                                          
Orderid-479959 38=723 Clientid=884
Orderid-24780 38=470 Clientid=405
Orderid-799794 38=350 Clientid=216
Orderid-72896 38=17 Clientid=735
0