One liner to retrieve a data block by a block

I always deal with data files, which consist of many data blocks in the following format:

*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
)

In any case, can I extract a "name" that I was interested in using single-line from the command line?

+3
source share
6 answers

Using this file for demo purposes:

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
)

This one line (divided by readability):

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

or minimum character version:

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

gives you:

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
)

which, I believe, is what you were.

This is basically a simple state machine that turns on printing when it finds the right block start and turns it off when it finds the end of this block.

UPDATE. perl- , _clock. : -)

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.=$_;}}'
+1

, Pax one

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

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

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

"*name* attr (" ")" , (, foo - , data.txt - ):

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

, Perl, 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 = '';
}

,

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

script. .

0

Perl:

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

I see in your comments another answer that you also want to search in the block for a string like QUALIFIED_CLOCK.

In this case , if your data blocks are separated by an empty string , you can use the Perl paragraph mode to read it in blocks and print the ones you are interested in. For example: p>

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

This is also possible in awk by installing RS.

-1
source

Source: https://habr.com/ru/post/1705770/


All Articles