Переместить шаблон из определенной строки в конец этого правила
Мне интересно, как я могу переместить шаблон, расположенный после определенной строки, в другое место правила.
Рассмотрим следующий пример:
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
)
- В поисках паттерна
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
}
Проверено следующее регулярное выражение в 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
После регулярного выражения: