【问题标题】:Conditional editing of line by one-liner逐行条件编辑
【发布时间】:2021-07-25 14:52:06
【问题描述】:

我的问题更多的是优化问题,而不是“操作方法”。
我有一个 lef 文件,有数千行,格式如下:

RECT 429.336 273.821 426.246 274.721 ;

我想使用单线将某个点以上的所有矩形向左移动 4 um:

perl -lane '$F[2] > 1200 ? print $F[0]," ", ($F[1] - 4)," ", $F[2]," ", ($F[3] -4)," ", $F[4], " ;" : print $_' trial.lef

问题是,这是丑陋的
有没有更好的方法来编辑文件?

我不挑剔,很乐意用其他语言(awk、sed 等)获得答案,只要它们比我写的更好。

附加输入:

      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

【问题讨论】:

  • “丑陋”是高度主观的。你喜欢perl -lane 'map $_ -= 4, @F[1,3] if $F[2] &gt; 1200; print "@F"' trial.lef吗?
  • 当然。我不知道地图功能,你只是介绍给我!这比我写的更好(据我所知)
  • 其实我的代码在滥用map。它利用$_ 是列表值的别名并且可以(ab)用来修改它的特性。所以我会说代码很短但晦涩难懂。它可能适用于单行代码,但永远不适用于生产代码。

标签: perl one-liner


【解决方案1】:

确实没有太大的改进空间,但是您可以将-n 替换为-p 以跳过额外的print。此外,您可以编辑数组元素并使用join 获得更漂亮的代码:

perl -lape'if ($F[2] > 1200) { $F[1] -= 4; $F[3] -= 4; $_ = join " ", @F }'
  • -a 自动拆分模式,将行 $_ 拆分为空间并将值放入预定义的 @F 数组中。此开关与-n-p 一起使用。
  • -p 围绕 &lt;&gt; 运算符输入、文件或标准输入循环
  • -= 按 RHS 中的数量减少 LHS
  • join 完成数学运算后重新组合在一起
  • -l 在这种情况下可以跳过,因为我们从不触及行尾,但如果我们决定编辑最后一个字段,保持它会使代码更加灵活。

不满足条件时,原行原样打印。否则,将替换为 @F 中的连接值。

如果您决定在 RECT 之前保留前导空格,您可以在 if 语句周围加上

if (($pre) = /^(\s*RECT)/)

存储行首,制作单行:

perl -lape'if (($pre) = /^(\s*RECT)/) { if ($F[2] > 1200) { $F[1] -= 4; $F[3] -= 4; $F[0] = $pre; $_ = join " ", @F }}'

【讨论】:

  • 嗯,嗯 - 这有点作弊,你把 3 行塞进一个括号里,但似乎足够有效。现在不接受,看看会不会出现其他有趣的解决方案...
  • 在单行中使用分号分隔的多行是常见的做法,这没有作弊。然而,我的代码和你的代码之间的一个区别是,你的代码会在第 5 个字段之后截断你的行,而我的不会。
  • 另外,如果您想在行前保留空格,可能需要对您的代码进行一些调整。
  • 是的,空格不是问题。截断对你来说是 1-0,我会给你。
  • 不过,保持格式很好,所以我找到了一种方法。
猜你喜欢
  • 1970-01-01
  • 2019-12-31
  • 2014-01-08
  • 1970-01-01
  • 1970-01-01
  • 2018-02-28
  • 2019-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多