2

I am using the below SED command:

sed '/cell.* '"alatch {"'/,/^}/p' -n file

Input file is as under:

cell abc { 
    pins on T {
        a b c
    }
    
}
cell xyz { 
    pins on T {
        x y z
    }
    
}

cell alatch { 
    pins on T {
        VSS VDDPI VDDP
    }
    pins on L {
        IN CT CB
    }
    pins on R {
        OUT
    }
    inputs {
        CB CT IN
    }
    outputs {
        OUT
    }
}
cell alatch { 
    pins on T {
        VSS VDDPI VDDP
    }
    pins on L {
        IN CT CB
    }
    pins on R {
        OUT
    }
    inputs {
        CB CT IN
    }
    outputs {
        OUT
    }
}


Output is as under:

cell alatch { 
    pins on T {
        VSS VDDPI VDDP
    }
    pins on L {
        IN CT CB
    }
    pins on R {
        OUT
    }
    inputs {
        CB CT IN
    }
    outputs {
        OUT
    }
}
cell alatch { 
    pins on T {
        VSS VDDPI VDDP
    }
    pins on L {
        IN CT CB
    }
    pins on R {
        OUT
    }
    inputs {
        CB CT IN
    }
    outputs {
        OUT
    }
}

Expected out is as under:

cell alatch { 
    pins on T {
        VSS VDDPI VDDP
    }
    pins on L {
        IN CT CB
    }
    pins on R {
        OUT
    }
    inputs {
        CB CT IN
    }
    outputs {
        OUT
    }
}

What is needed is that only the first occurrence should be the output. Any suggestion for command?

1
  • Clarify the exact occurrence of what you want. Also, I don't think your quoting, while probably not incorrect, makes much sense and only obfuscates the sed command. How about '/cell.* alatch {/,/^}/p' as a start? Feb 15, 2021 at 10:54

2 Answers 2

5

Assuming you want the first of the two identical blocks:

$ sed '/cell alatch {/,/^}/!d; /^}/q' file
cell alatch {
    pins on T {
        VSS VDDPI VDDP
    }
    pins on L {
        IN CT CB
    }
    pins on R {
        OUT
    }
    inputs {
        CB CT IN
    }
    outputs {
        OUT
    }
}

The /cell alatch {/,/^}/ range is the range of lines that you want to get as output.

The sed expressions first deletes all lines not in this range, and then quits as soon as a } is found at the start of a line. The q instruction will cause sed to terminate after it outputs the current line, so the final } will get printed.

Executing the d instruction immediately skips to the next input line and branches back to the start of the editing script, so the q instruction has no way of executing unless it's in the range which does not cause d to execute.


With awk, achieving the same effect with code that should be reminiscent of the sed code above:

$ awk '/cell alatch {/,/^}/ { print; if ($0 ~ /^}/) exit }' file
cell alatch {
    pins on T {
        VSS VDDPI VDDP
    }
    pins on L {
        IN CT CB
    }
    pins on R {
        OUT
    }
    inputs {
        CB CT IN
    }
    outputs {
        OUT
    }
}

Actually, this is closer to the sed command

sed -n '/cell alatch {/,/^}/{ p; /^}/q; }' file

which does the same thing.

2

With awk we accumulate the desired cell data and when the depth (number of { = number of } reaches 0 we dump the cell data nd quit.

awk '
  BEGIN { ORS = "" }
  /cell alatch \{/ {inCell=1}
  !inCell {next}
  {data = data $0 RS} 
  /\}/ {depth--} 
  /\{/ {depth++}
  !depth {
    print data 
    exit
  }
' ./file

Using GNU sed with the same idea of the awk code above.

sed -e '
  /cell alatch {/!d
  /\n/!{h;s/.*/x/;x;}
  $d;N
  /}$/{x;s/x//;/x/!{x;q;};x;}
  /{$/{x;s/$/x/;x;}
  s/^/\n/;D
' file

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .