【问题标题】:Move a pattern from specific line to end of that rule [closed]将模式从特定行移动到该规则的末尾[关闭]
【发布时间】:2016-10-21 05:28:30
【问题描述】:

我想知道如何将放置在某行之后的模式移动到规则的另一个位置。

考虑下面的例子,

rule tmap {

  hideON 
   student_analysis Sam -expr "marks(Sam)" -gt 0
  hideOFF

  -Designate [ School = "ABC]
  -Designate [ Name = "Sam" ]
  -Designate [ Country= "ABC]
  -Designate [ State = "Sam"]
  -Designate [ ROLL Number= "Sam"]
}

其中 hideOFF 需要从 student_analysis 移动到结束大括号之前。输出文件应该有类似

rule tmap {

      hideON 
       student_analysis Sam -expr "marks(Sam)" -gt 0


      -Designate [ School = "ABC]
      -Designate [ Name = "Sam" ]
      -Designate [ Country= "ABC]
      -Designate [ State = "Sam"]
      -Designate [ ROLL Number= "Sam"]
     hideOFF
    }

仅添加这些 -Designate 条目可能位于单行中,因此行数不应成为标准。我的输入文件可能像

 rule tmap {

      hideON 
       student_analysis Sam -expr "marks(Sam)" -gt 0
      hideOff

      -Designate [ School = "ABC] -Designate [ Name = "Sam" ] -Designate [ Country= "ABC] -Designate [ State = "Sam"] -Designate [ ROLL Number= "Sam"]

    }

如果您需要更多说明,请告诉我。

基于 Peters 帮助的最终解决方案

#!/usr/bin/tclsh
set fileData [lindex $argv 0 ]
set fp [open $fileData r]
set data [read $fp]
set lines [split [string trim $data] \n]
set hideoff {}
foreach line $lines {
  if {[regexp {^\s*hideoff\s*} $line match ] == 1 } {
        set hideoff $line
   } elseif {[regexp {^\s*\}\s*} $line match ] == 1 } {
        puts $hideoff
        puts $line
    } else {
        puts $line
    }
}

感谢大家提出这么好的建议。

【问题讨论】:

  • 你有没有尝试解决这个问题,你在哪里失败了?
  • 我还没有为它编写任何代码。只是想知道是否有人以前遇到过这样的事情。
  • @DiveshRastogi:你至少应该尝试。 Stack Overflow 是 帮助 的来源,而不是免费完成工作的地方。

标签: perl shell tcl


【解决方案1】:

您可以使用ex text-editor,它在所有 Unix/Linux 变体中都可用,以简单/单行形式实现此目的

printf '%s\n' '/hideOFF' 'd' '/}' '-' 'put' 'wq' | ex file

ex 编辑器结构类似于vi 的语法。我为此采用的逻辑如下(记住就像你在vi/vim中打开文件一样)

  1. 搜索模式hideOFF'/hideOFF',使用d 命令键将其删除。
  2. 现在搜索右大括号 /}-put 从大括号上方的寄存器写入行
  3. wq 将内容写回到文件中。

您可以在下面看到它的工作原理。

$ cat file
rule tmap {

  hideON
   student_analysis Sam -expr "marks(Sam)" -gt 0
  hideOFF

  -Designate [ School = "ABC]
  -Designate [ Name = "Sam" ]
  -Designate [ Country= "ABC]
  -Designate [ State = "Sam"]
  -Designate [ ROLL Number= "Sam"]
}

直接在命令行运行命令:-

$ printf '%s\n' '/hideOFF' 'd' '/}' '-' 'put' 'wq' | ex file
$ cat file
rule tmap {

  hideON
   student_analysis Sam -expr "marks(Sam)" -gt 0

  -Designate [ School = "ABC]
  -Designate [ Name = "Sam" ]
  -Designate [ Country= "ABC]
  -Designate [ State = "Sam"]
  -Designate [ ROLL Number= "Sam"]
  hideOFF
}

【讨论】:

  • 谢谢伊尼安。不幸的是,该解决方案仅适用于第一种模式,铰孔模式保持不变。
  • @DiveshRastogi:您在问题中只提供了一个模式。剩余模式是什么意思?
【解决方案2】:

您需要重新编写文件,一旦您这样做了,任何语言都非常简单。

逐行复制并将它们复制到一个新文件中。当您来到hideOFF 行时不要将其写入 到新文件中,只需保存到变量中即可。然后,当您到达该块的右大括号时,写出变量(带行)和大括号。这将在带有大括号的行之前移动带有hideOFF 的行。

你需要一个标志来知道你何时进入和离开一个街区。

请试一试,告诉我们进展如何。

【讨论】:

    【解决方案3】:

    (Tcl 解决方案) 您可以通过重新打印行来做到这一点。您先查看它们,跳过要移动的行,然后在看到之前要插入的行时打印它。

    set lines [split [string trim $data] \n]
    
    set hideoff {}
    foreach line $lines {
        if {[string trim $line] eq "hideOFF"} {
            set hideoff $line
        } elseif {[string trim $line] eq "\}"} {
            puts $hideoff
            puts $line
        } else {
            puts $line
        }
    }
    

    另一种 Tcl 解决方案:

    regsub -all {(\s*hideOFF)([^\}]+)} $data \\2\\1\n
    

    两种解决方案都适用于多个块。

    文档: eq (operator), foreach, if, puts, regsub, set, split, string, Syntax of Tcl regular expressions

    【讨论】:

    • #!/usr/bin/tclsh set fileData [lindex $argv 0 ] set fp [open $fileData r] set data [read $fp] set lines [split [string trim $data] \ n] set hideoff {} foreach line $lines { if {[regexp {^\shideoff\s} $line match ] == 1 } { set hideend $line } elseif {[regexp {^ \s*\}\s*} $line match ] == 1 } { puts $hideoff puts $line } else { puts $line } }
    • 谢谢彼得。我用正则表达式替换了字符串修剪,它适用于我的情况。感谢您的帮助。
    【解决方案4】:

    在 VIM 中测试了以下正则表达式,它完全符合您的要求:

    %s/hideOFF\(\_.*\)}/\1\rhideOFF\r}/i
    
    **Explanation:**
    %s - Search across the file 
    \( \) - Used to capture a group of text to be used in replace section 
    \_.* - Capture everything, including new lines 
    \1 - Insert captured group here  
    \r - new line
    

    我参考了以下两个来源:

    http://vim.wikia.com/wiki/Search_across_multiple_lines & Vim Regex Capture Groups

    原文:

    正则表达式之后:

    【讨论】:

    • 感谢 J Atwal。这是一个有趣的解决方案,但仅适用于最后两种模式。我的文件中大约有 11K 行,8k 包含相同的模式。
    • @DiveshRastogi:你的问题根本没有提到这一点。我们应该如何预测您不提供的信息?
    • 用问题陈述中提到的 tcl 解决方案解决。
    猜你喜欢
    • 2015-09-05
    • 1970-01-01
    • 2014-05-19
    • 2017-07-17
    • 2015-02-28
    • 2021-01-03
    • 2021-09-11
    • 2020-06-09
    相关资源
    最近更新 更多