【问题标题】:String replace using sed in tcl script - string contains round brackets在 tcl 脚本中使用 sed 替换字符串 - 字符串包含圆括号
【发布时间】:2019-08-24 10:00:25
【问题描述】:

我想在 tcl 脚本中使用 sed 来修改包含字符串的文件(存储在 $file 中):

prbs_match_out

prbs_match_out

尝试:

exec /bin/sed -i {s/(ch0_prbs_match_dual3_int  &  ch0_prbs_match_dual2_int  &  ch0_prbs_match_dual1_int  &  ch0_prbs_match_int) & (   ch1_prbs_match_dual3_int  &  ch1_prbs_match_dual2_int  &  ch1_prbs_match_dual1_int  &  ch1_prbs_match_int)/ch0_prbs_match_int & ch1_prbs_match_int/g}  $file

上述 sed 命令不起作用(得到不正确的替换)。如何在 sed 中处理圆括号和 & 符号?

【问题讨论】:

  • 您能否将您的问题简化为“将任何以prbs_match_out <= 开头的行替换为prbs_match_out <= ch0_prbs_match_int & ch1_prbs_match_int;,或者您所包含的大行真的是您需要修复的唯一prbs_match_out <= 版本吗?另外,请阅读grymoire.com/Unix/Sed.html。祝你好运。
  • 我只想修复行(唯一)prbs_match_out <= (ch0_prbs_match_dual3_int & ch0_prbs_match_dual2_int & ch0_prbs_match_dual1_int & ch0_prbs_match_int) & ( ch1_prbs_match_dual3_int & ch1_prbs_match_dual2_int & ch1_prbs_match_dual1_int & ch1_prbs_match_int);
  • 另请注意,sed 无法轻松匹配跨越多行文本的模式。在您的示例数据中不清楚这是一行连续的文本还是跨多行格式化。您需要转义括号和 & 字符,因为它们对于 sed 正则表达式具有特殊含义。所以(也许)s/\(ch0_prbs_match_dual3_int \& ....\) ... 根据您使用的 sed 版本以及您包含的任何选项,您可能不需要转义括号。最好先让一个小样本工作,然后在你的全线上尝试。祝你好运。
  • 在 sed 的 BRE 中,括号和 & 号没有特殊含义。 & 确实s 命令的replacement 部分具有特殊含义。如果您使用sed -rsed -E 运行sed,那么您使用的是ERE,并且括号在模式中变得特殊。
  • @LokSas,您的问题的格式使其难以重现。您的输入是否包含换行符?多个空格是否重要?

标签: regex string sed tcl substitution


【解决方案1】:

我想通了——tcl 的“字符串映射”命令有效。感谢您的帮助。

package require Tcl 8.5

package require fileutil

# Parameters for the replacement 
set from "(   ch0_prbs_match_dual3_int  &  ch0_prbs_match_dual2_int  &  ch0_prbs_match_dual1_int  &  ch0_prbs_match_int) & (   ch1_prbs_match_dual3_int  &  ch1_prbs_match_dual2_int  &  ch1_prbs_match_dual1_int  &  ch1_prbs_match_int)"
set to "ch0_prbs_match_int & ch1_prbs_match_int"

# Which file to replace 
set checkingFile /proj/dada/test.v

# Make a command fragment that performs the replacement on a supplied string
set replacementCmd [list string map [list $from $to]]

# For single file replacement 
fileutil::updateInPlace $checkingFile $replacementCmd

【讨论】:

    【解决方案2】:

    如果变量中有文件contents(或文件的一行),则可以使用string map 命令将一个子字符串替换为其他文本。

    【讨论】:

      【解决方案3】:

      BRE(基本正则表达式)中,只能转义六个字符 从字面上处理:^$.*\[.
      另外,你需要逃跑 &s 命令的REPLACEMENT 部分sed,因为&PATTERN 中匹配的部分有特殊含义。
      因此,您可以这样说:

      #!/usr/bin/tclsh
      
      set file {yourfilename}
      exec /bin/sed -i {s/(ch0_prbs_match_dual3_int & ch0_prbs_match_dual2_int & ch0_prbs_match_dual1_int & ch0_prbs_match_int) & ( ch1_prbs_match_dual3_int & ch1_prbs_match_dual2_int & ch1_prbs_match_dual1_int & ch1_prbs_match_int);/ch0_prbs_match_int \& ch1_prbs_match_int;/} $file
      

      $file修改为:

      prbs_match_out <= ch0_prbs_match_int & ch1_prbs_match_int;
      

      【讨论】:

      • 你不能确切地说...因为这是经典的单引号时调用shell命令问题(注意标签tcl)。最近都回答过了,暂时不想再回答了……
      • 非常感谢您的建议。我会记住的:-)。
      • @DonalFellows 原来sed 命令只需将引号从单引号修改为花括号,这样就可以在tcl 中执行。
      • 感谢您的回复和解释,但没有奏效:(
      • @LokSas 您能否具体说明它是如何not 工作的(例如输出、错误消息等),包括您的sedtcl 版本?我已经使用 sed (GNU sed) 4.2.2 和 tclsh 8.6 进行了测试。如果您已经用其他人的答案解决了问题,那么您无论如何都不必花费时间来回答此评论。 BR。
      【解决方案4】:

      您是否考虑过使用 Tcl 进行这种就地转换,例如通过其[regsub] 命令:

      set x [regsub {(\([^)]*\))} $x ch0_prbs_match_int]
      set x [regsub {(\([^)]*\))} $x ch1_prbs_match_int]
      

      只修行(唯一)

      这假定变量 x 保存文件的内容,并且可以通过注意匹配的括号对来唯一标识要替换的行元素。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-12
        • 1970-01-01
        • 1970-01-01
        • 2017-08-04
        • 2020-07-23
        • 2022-07-21
        • 2021-12-01
        • 1970-01-01
        相关资源
        最近更新 更多