2009-04-02 2 views
3

Je traite toujours avec des fichiers de données qui se composent de plusieurs blocs de données du format suivant:une doublure pour extraire le bloc de données par bloc

*name* attr (
     VALID (
       late_lead_up xxx ar uclk reff xxx slope xxx 
       late_lead_dn xxx af uclk reff xxx slope xxx 
       early_trail_up xxx af uclk reff xxx slope xxx 
       early_trail_dn xxx ar uclk reff xxx slope xxx 
      ) 
     CEXT xxx 
     CREF xxx 
     REFF xxx 
     QUALIFIED_CLOCK 
) 

Y at-il de toute façon je peux extraire le « nom » que je intéressé à utiliser un one-liner de la ligne de commande?

+0

Savez-vous combien de lignes le bloc est? –

+0

le nombre de ligne n'est pas fixe –

+0

do * name * et ses parenthèses fermantes apparaissent au début de la ligne? Est-ce que quelque chose d'autre apparaît au début de la ligne? –

Répondre

1

L'utilisation de ce fichier à des fins de démonstration:

of_interest attr (
    1:VALID (
     1:late_lead_up xxx ar uclk reff xxx slope xxx 
     1:late_lead_dn xxx af uclk reff xxx slope xxx 
     1:early_trail_up xxx af uclk reff xxx slope xxx 
     1:early_trail_dn xxx ar uclk reff xxx slope xxx 
    1:) 
    1:CEXT xxx 
    1:CREF xxx 
    1:REFF xxx 
    1:QUALIFIED_CLOCK 
) 

boring attr (
    2:VALID (
     2:late_lead_up xxx ar uclk reff xxx slope xxx 
     2:late_lead_dn xxx af uclk reff xxx slope xxx 
     2:early_trail_up xxx af uclk reff xxx slope xxx 
     2:early_trail_dn xxx ar uclk reff xxx slope xxx 
    2:) 
    2:CEXT xxx 
    2:CREF xxx 
    2:REFF xxx 
    2:QUALIFIED_CLOCK 
) 

of_interest attr (
    3:VALID (
     3:late_lead_up xxx ar uclk reff xxx slope xxx 
     3:late_lead_dn xxx af uclk reff xxx slope xxx 
     3:early_trail_up xxx af uclk reff xxx slope xxx 
     3:early_trail_dn xxx ar uclk reff xxx slope xxx 
    3:) 
    3:CEXT xxx 
    3:CREF xxx 
    3:REFF xxx 
    3:QUALIFIED_CLOCK 
) 

Cette ligne unique (split pour une meilleure lisibilité):

awk ' 
    BEGIN    {s=0} 
    /^of_interest/ {s=1} 
    /^)$/    {if (s==1) {print};s=0} 
         {if (s==1) print}' 

ou la version de caractères minimum:

awk 'BEGIN{s=0}/^of_interest /{s=1}/^)$/{if(s==1){print};s=0}{if(s==1)print}' 

vous donne :

of_interest attr (
    1:VALID (
     1:late_lead_up xxx ar uclk reff xxx slope xxx 
     1:late_lead_dn xxx af uclk reff xxx slope xxx 
     1:early_trail_up xxx af uclk reff xxx slope xxx 
     1:early_trail_dn xxx ar uclk reff xxx slope xxx 
    1:) 
    1:CEXT xxx 
    1:CREF xxx 
    1:REFF xxx 
    1:QUALIFIED_CLOCK 
) 
of_interest attr (
    3:VALID (
     3:late_lead_up xxx ar uclk reff xxx slope xxx 
     3:late_lead_dn xxx af uclk reff xxx slope xxx 
     3:early_trail_up xxx af uclk reff xxx slope xxx 
     3:early_trail_dn xxx ar uclk reff xxx slope xxx 
    3:) 
    3:CEXT xxx 
    3:CREF xxx 
    3:REFF xxx 
    3:QUALIFIED_CLOCK 
) 

que je crois est ce que vous étiez après.

C'est fondamentalement une machine à états simple qui allume l'impression quand elle trouve le début de bloc désiré et l'éteint quand elle trouve la fin de ce bloc.

MISE À JOUR: Voici un doublage perl qui prend en charge votre exigence qualifiée_clock. Profitez :-)

perl -e '$s=1;while(<STDIN>){if(/^of_interest /){$s=1;$f=0;$x="";}if(($s==1)&&/QUALIFIED_CLOCK/){$f=1;}if(/^\)$/){if($s==1){$x.=$_;}if($f==1){print$x;}$s=0;next;}if($s==1){$x.=$_;}}' 
+0

que se passe-t-il si un bloc de données a QUALIFIED_CLOCK et que d'autres n'en ont pas, et que j'aimerais extraire tous les blocs avec QUALIFIED_CLOCK? –

+0

Ensuite, vous devrez stocker les lignes plutôt que de les imprimer, effacer un drapeau au démarrage du bloc, le définir si vous trouvez QUALIFIED_CLOCK et, lorsque vous trouvez le bloc, afficher toutes les lignes si le drapeau est activé. – paxdiablo

+0

S'il y a plus de changements dans les exigences, je choisirais de passer à une solution basée sur Python/Perl, mais ce ne sera pas une ligne lisible dans n'importe quelle langue :-) – paxdiablo

0

Si votre bloc commence toujours par « *name* attr ( » et se termine toujours par un « ) » seul, sans espace de premier plan, vous pouvez essayer (étant donné que foo est le nom du bloc et data.txt est le fichier pour analyser):

awk '/ attr \($/ {if($1==n)b=1} {if(b)print} /^\)$/ {b=0}' n=foo data.txt 
0

Eh bien, vous indéxé Perl, alors voici comment je le ferais en Perl:

#!/usr/bin/perl 

use strict; 
use warnings; 

die "usage: $0 name datafile\n or cat datafile | $0 name\n" 
    unless @ARGV > 0; 

my $name = shift; 
my $re = qr/\A$name attr/; 

my $rec = ''; 
while (my $line = <>) { 
    $rec .= $line; 
    next unless $line =~ /^\)/; 
    print $rec if $rec =~ /$re/; 
    $rec = ''; 
} 

vous pouvez transformer en un comme un liner, ce

perl -ne '$a.=$_;next unless/^\)/;print$a if$a=~/^name/;$a=""' datafile 

mais je préfère le script. N'oubliez pas de remplacer le nom par le nom de l'enregistrement.

-1

Voici une façon de lui en tant que Perl one-liner:

perl -ne '$m = 1 if /^insert_name_here attr/; print if $m; $m = 0 if /^\)$/' file.txt 
-1

Je vois dans vos commentaires à une autre réponse que vous souhaitez également effectuer des recherches dans le bloc pour une chaîne comme 'QUALIFIED_CLOCK'.

Dans ce cas, si vos blocs de données sont séparées par une ligne blanche vous pouvez utiliser le mode paragraphe de Perl pour lire dans les blocs et imprimer ceux qui vous intéressent. Par exemple:

perl -00 -ne 'print if /^block_name/ and /QUALIFIED_CLOCK/' file.txt 

Ceci est également possible dans awk en réglant RS.

+0

Votre solution est élégante! Merci beaucoup. –

1

beaucoup moins caractères et une solution plus simple que Pax'sone

perl -ne '/^of_interest /../^\)/ and print' 

ou

awk '/^of_interest /,/^\)/{print}' 

ou

sed -n '/^of_interest /,/^)/p'