Переместить шаблон из определенной строки в конец этого правила

Мне интересно, как я могу переместить шаблон, расположенный после определенной строки, в другое место правила.

Рассмотрим следующий пример:

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

    }

В случае, если вам нужно больше разъяснений, пожалуйста, дайте мне знать.

Окончательное решение на основе помощи Питера

#!/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 ответа

Решение

(Решение 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 (оператор), foreach, if, put, regsub, set, split, string, синтаксис регулярных выражений Tcl

Вам нужно переписать файл, и как только вы это сделаете, это очень просто для любого языка.

Идите строка за строкой и скопируйте их в новый файл. Когда вы приходите к hideOFF Строка не записывать его в новый файл, просто сохранить в переменную. Затем, когда вы придете к закрывающей скобке этого блока, выведите переменную (со строкой) и скобку. Это переместит линию с hideOFF прямо перед линией со скобой.

Вам понадобится флаг, чтобы знать, когда вы входите и выходите из блока.

Пожалуйста, попробуйте и дайте нам знать, как это происходит.

Ты можешь использовать ex текстовый редактор, который доступен во всех вариантах 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
}

Проверено следующее регулярное выражение в 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

Первоначальный текст:

После регулярного выражения:

Другие вопросы по тегам