My question is more of an optimization one, rather then a "howto".
I have a lef file, with thousands of lines in the form of:
RECT 429.336 273.821 426.246 274.721 ;
I wanted to move left by 4 um all rects above a certain point using a one-liner:
perl -lane '$F[2] > 1200 ? print $F[0]," ", ($F[1] - 4)," ", $F[2]," ", ($F[3] -4)," ", $F[4], " ;" : print $_' trial.lef
Thing is, this is UGLY.
Is there a nicer way of editing the file?
I'm not picky and will be happy to have answers with other languages (awk, sed, etc.) as long as they are nicer than what I wrote.
Additional input:
LAYER M12 ;
RECT 0 411.214 1 412.214 ; <-- shouldn't change, because 411.214 < 1200
END
END kuku_pin
PIN gaga_pin
DIRECTION OUTPUT ;
USE SIGNAL ;
PORT
LAYER M11 ;
RECT 43.1045 1203.138 43.1805 1207.29 ; <-- should change to "RECT 39.1045 1203.138 39.1805 1207.29"
END
There really is not much room for improvement, but you can replace -n
with -p
to skip the extra print
. Further, you can edit the array elements and use join
for a bit prettier code:
perl -lape'if ($F[2] > 1200) { $F[1] -= 4; $F[3] -= 4; $_ = join " ", @F }'
-a
autosplit mode, splits the line $_
on space and puts the values in the predefined @F
array. This switch is used with -n
or -p
.-p
loops around the <>
operator input, file or standard input-=
decreases the LHS by amount in RHSjoin
joins the line back together after math has been done-l
can be skipped in this case, since we never touch the line endings, but keeping it makes the code more flexible if we decide to edit the last field.When the condition is not met, original line is printed unchanged. Otherwise, it is replaced with the joined values in @F
.
If you decide to keep the leading whitespace before RECT
you can surround your if-statement with
if (($pre) = /^(\s*RECT)/)
To store the beginning of the line, making the one-liner:
perl -lape'if (($pre) = /^(\s*RECT)/) { if ($F[2] > 1200) { $F[1] -= 4; $F[3] -= 4; $F[0] = $pre; $_ = join " ", @F }}'