将模式从特定行移动到该规则的末尾

时间:2016-10-21 05:28:31

标签: perl shell tcl

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

考虑以下示例,

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
    }
}

感谢大家提出的好建议。

4 个答案:

答案 0 :(得分:1)

您可以使用所有Unix / Linux变体中提供的ex text-editor来实现此目的,简单/单行

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

ex编辑器构造类似于vi的语法。我采用的逻辑如下(记住好像你在vi / vim打开文件)

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

    $ 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
    }
    

答案 1 :(得分:1)

你需要重新编写文件,一旦你这样做,任何语言都很简单。

逐行浏览并将其复制到新文件中。当你来到hideOFF不要将它写入新文件时,只需保存到变量中即可。然后,当你到达那个块的右括号时,写出变量(带有线)和大括号。这将使hideOFF的线移动到支撑线的前面。

您需要一个标志才能知道您何时进入和离开区块。

请尝试一下,让我们知道它是怎么回事。

答案 2 :(得分:0)

在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

原文: enter image description here

在Regex之后:

enter image description here

答案 3 :(得分:0)

(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)foreachifputsregsubsetsplitstringSyntax of Tcl regular expressions