Подходим внутренний шаблон. Многострочный - PullRequest
1 голос
/ 25 марта 2012

У меня есть:

%{ lorem ipsum dolor 
   sit %{hello
           world}%
   amet}%

Я хочу:

 hello
   world

То есть я хочу сохранить внутреннюю %{...}% любого числа вложений %{...}% s, которые могутили не может занимать несколько строк.

Есть ли способ sed или awk?

Ответы [ 3 ]

2 голосов
/ 25 марта 2012

Эта sed команда:

sed -n -r 'H; ${g; s/([^}]|\}[^%])*%\{//; s/\}%([^%]|%[^{])*//; p}'

соберет весь ввод в пространство шаблона, затем удалит ...%{ (заботясь о том, чтобы ... не содержал }%) и }%... (заботясь о том, чтобы ... не содержит %{), а затем выведите результат. Так что это подходит для случая, когда вам нужен только один блок. Случай с несколькими блоками сложнее, но я подумаю над этим и уточню этот ответ, если мне это удастся.

Обратите внимание, что -r (для поддержки расширенных регулярных выражений вместо базовых) является расширением GNU для sed, поэтому, если вы используете не-GNU sed, который его не поддерживает, я знаю.


Отредактировано, чтобы добавить: О.К., вот версия, которая поддерживает несколько блоков:

sed -n -r 'H; ${g; s/^([^}]|\}[^%])*%\{//; s/\}%([^%]|%[^{])*$//; s/\}%([^%]|%[^{])*([^}]|\}[^%])*%\{/\n/g; p}'

Он использует по существу тот же подход, что и предыдущий, за исключением того, что он удаляет только ...%{ в начале ввода и }%... в конце ввода, а после этого он удаляет все экземпляры }%...%{, которые не содержат %{...}%, заменяя их символом новой строки.

1 голос
/ 25 марта 2012

Один из возможных способов TXR:

Просто просканируйте входную произвольную форму (в виде одной большой строки), собирая совпадения для регулярного выражения в переменную wanted, которая неявно собирается в список с именем wanted.

Затем выплюните кусочки, отрубая по два символа из головы и хвоста каждого.

$ txr -c '@(freeform)
@(coll)@{wanted /\%{(~(.*(\%{|}\%).*))}\%/}@(end)
@(output)
@(rep)@{wanted [2..-2]}@(end)
@(end)' -
asdf asdf %{
  %{ asdf
asdf             
}% %{boo}% }%
[Ctrl-D][Enter]
 asdf
asdf 
boo

Оператор regex ~ означает дополнение.Переменная wanted захватывает текст, который состоит из %{, за которым следует самая длинная совпадающая строка, которая не содержит %{ или }% в качестве подстроки, за которой следует %}.Регулярное выражение TXR поддерживает дополнение, пересечение, различие.Мы должны написать \% символ, потому что % является нежадным оператором ноль или более.

Вывод для примера, приведенного в вопросе:

hello
           world

а не

hello
  world

Автор не уточнил, действительно ли это необходимо.Это усложняет проблему, потому что %{hello происходит где-то в середине строки, и поэтому мы должны знать положение столбца h в hello, чтобы знать, что w в world - это два пробелаболее.

1 голос
/ 25 марта 2012

Способ AWK:

gawk '
/%{/ {
    match($0,/%{.*/)
    text=substr($0,RSTART+2,RLENGTH-2)
}
!/% {/ && !/}%/ {
    text=text "\n" $0
}
/}%/ {
    match($0,/}%/)
    text=text "\n" substr($0,1,RSTART-1)
    print text
    exit
}'

Это не будет работать, если в одной строке более одного {% или%}. В этом случае вам нужна небольшая модификация - используйте массив в команде match.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...