-2

I am wondering how can I move a pattern placed after certain line to another location of a rule.

Consider the following example,

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

where hideOFF needs to be moved from student_analysis to just before the end curly braces. Output file should have something like

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
    }

Just to add these -Designate entries might be in a single row so number of row should not be a criterion. I might have my input file like

 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"]

    }

In case if you need more clarification, please let me know.

Final solution Based on Peters help

#!/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
    }
}

Thanks everyone for so nice suggestions.

4 Answers4

1

You can use ex text-editor which is available in all Unix/Linux variants to achieve this, in simple/single line as

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

The ex editor constructs are similar to the vi's syntax. The logic I adopted for this is as below (Remember as if you are opening the file in vi/vim)

  1. Searching for the pattern hideOFF as '/hideOFF', deleting it using d command key.
  2. Now searching for the close-brace /}, - and put writes the line from the register above the brace
  3. wq writes back the contents to the file.

You can see it working below.

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

Running the command directly on command-line:-

$ 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
}
Inian
  • 80,270
  • 14
  • 142
  • 161
  • Thanks Inian. Unfortunately, that solution works for only first pattern and reaming patterns remain as it is. – Divesh Rastogi Oct 21 '16 at 06:14
  • 2
    @DiveshRastogi: You provided only a single pattern in your question. What do you mean remaining patterns? – Inian Oct 21 '16 at 06:16
1

You need to re-write the file, and once you are doing that it's very simple with any language.

Go line by line and copy them to a new file. When you come to hideOFF line do not write it to the new file, just save into a variable. Then, when you come to the closing brace of that block write out the variable (with the line) and the brace. This will have moved the line with hideOFF right before the line with the brace.

You'll need a flag to know when you enter and leave a block.

Please try it out and let us know how it is going.

zdim
  • 64,580
  • 5
  • 52
  • 81
0

Tested following regex in VIM and it does exactly what you require:

%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

I referred to following two sources:

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

Original text: enter image description here

After Regex:

enter image description here

Community
  • 1
  • 1
J Singh
  • 162
  • 5
  • Thanks J Atwal. This is an interesting solution but just works for last two patterns. I roughly have 11K lines in my file and 8k contain same kind of pattern. – Divesh Rastogi Oct 21 '16 at 06:16
  • 2
    @DiveshRastogi: Your question doesn't mention that at all. How are we supposed to divine information that you don't provide? – Borodin Oct 21 '16 at 08:38
  • resolved with tcl solution mentioned along with the problem statement. – Divesh Rastogi Oct 24 '16 at 05:42
0

(Tcl solution) You can do that by reprinting lines. You look at them first, skip the line you want to move and then print it when you see the line you want it inserted before.

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

Another Tcl solution:

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

Both solutions work for multiple blocks.

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

Peter Lewerin
  • 13,140
  • 1
  • 24
  • 27
  • #!/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 hideend $line } elseif {[regexp {^\s*\}\s*} $line match ] == 1 } { puts $hideoff puts $line } else { puts $line } } – Divesh Rastogi Oct 24 '16 at 05:32
  • Thanks Peter. I replaced string trim with regexp and it worked for my case. thanks for your help. – Divesh Rastogi Oct 24 '16 at 05:34