Perl 将图案从特定行移动到该规则的末尾

Perl 将图案从特定行移动到该规则的末尾,perl,shell,tcl,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"] -Design

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

考虑下面的例子

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_分析移动到刚好在结束花括号之前。输出文件应该有如下内容

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
    }
只需添加这些-指定项就可以在一行中,所以行数不应作为标准。我的输入文件可能是这样的

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

谢谢大家的建议。

在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
我提到了以下两个来源:

&

原文:

在正则表达式之后:

您可以使用在所有Unix/Linux变体中可用的,以简单/单行的形式实现这一点

printf '%s\n' '/hideOFF' 'd' '/}' '-' 'put' 'wq' | ex file
ex
编辑器结构类似于
vi
的语法。我为此采用的逻辑如下(请记住,就像在
vi
/
vim
中打开文件一样)

  • 将模式
    hideOFF
    搜索为
    '/hideOFF'
    ,使用
    d
    命令键将其删除
  • 现在搜索右大括号
    /}
    -
    put
    将寄存器中的行写入大括号上方
  • 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
    }
    
    (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
    
    这两种解决方案都适用于多个块

    文件: , , , , , , , ,

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

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

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


    请尝试一下,并让我们知道它是如何运行的。

    您是否尝试解决此问题,您在哪里失败了?我还没有为此编写任何代码。我只是想知道以前是否有人遇到过类似的事情。@Togi:你至少应该试试。堆栈溢出是一个帮助的来源,而不是一个免费完成工作的地方。谢谢。不幸的是,该解决方案只适用于第一种模式,而铰孔模式保持原样。@Devhratogi:您在问题中只提供了一种模式。你说剩下的图案是什么意思?谢谢J阿特瓦尔。这是一个有趣的解决方案,但只适用于最后两种模式。我的文件中大约有11K行,8k行包含相同的模式。@托吉:你的问题根本没有提到这一点。我们应该如何预测您未提供的信息?使用tcl解决方案以及问题声明解决了此问题。#/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*\s*}$line match]=1}{否则{put$line}谢谢彼得。我用regexp替换了string trim,它对我的案例有效。谢谢你的帮助。