Случаи замены VIM шаблона после конкретного слова в строке

Немного ужасной sed остроты:

sed -n  \
# we divide out incoming text to small parts, 
# each one as you mentioned from /---.*box.*/ to /profile/
'/---.*box.*/,/profile/{
     # inside of each part we do following things:
     # if string matches our pattern we extract 
     # the value and give it some identifier (which you
     # can see is "ij", "st" and so on)
     # and we copy that value with identifier to hold buffer,
     # but we don't replace the content of hold buffer
     # we just append (capital H) new var to it
     /insert_job/{s/[^:]*: /ij"/;s/ .*/",/;H};
     /start_times/{s/[^:]*: /st/;s/$/,/;H};
     /days_of_week/{s/[^:]*: /dw"/;s/$/",/;H};
     /machine/{s/[^:]*: /ma"/;s/$/",/;H};
     /description/{s/[^:]*: /de/;s/$/,/;H};
     /command/{s/[^:]*: /co"/;s/$/",/;H};
     # when line matches next pattern (profile)
     # we think that it is the end of our part,
     # therefore we delete the whole line (s/.*//;)
     # and exchange the pattern and hold buffers (x;)
     # so now in pattern buffer we have several strings with all needed variables
     # but all of them are in pattern space, therefore we can remove
     # all newlines symbols (s/\n//g;). so it is just one string 
     # with a list of variables
     # and we just need to move to the order we want,
     # so in this section we do it with several s commands.
     # after that we print the result (p)
     /profile/{s/.*//;x;s/\n//g;s/ij\("[^"]*box[^"]*",\)/\1/;
          s/,\(.*\)st\("[^"]*",\)\(.*ij"[^"]*",\)/,\2\1\3\2/;
          s/\([^,]*,[^,]*,\)\(.*\)dw\("[^"]*",\)\(.*ij"[^"]*",[^,]*,\)/\1\3\2\4\3/;
          s/de/"",/;s/ij/""\n/;
          s/\(\n[^,]*,[^,]*,[^,]*,\)\(.*\)ma\("[^"]*",\)/\1\3\2/;
          s/co\("[^"]*"\),\(.*\)/\2\1/;s/de//;p}
     };
     # the last command just adds table caption and nothing more.
     # note: if you want to add some new commands,
     # add them before this one
     1i"Job Name", "Time", "Schedule", "Machine", "Description", "Command"'

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

7
19.09.2013, 21:17
2 ответа

Можно использовать специальный атом \@<= утверждать соответствие прежде (=.* сделать его где угодно прежде в той строке):

:%s/\(=.*\)\@<=pattern/saturn/g
3
27.01.2020, 20:18
  • 1
    Вы могли объяснить, как это работает? –  user13107 21.09.2013, 13:47
  • 2
    Read :help /\@<= (Я не могу объяснить это лучше), но не плохо себя чувствуйте, когда Вы не получаете его сначала. Это назвало положительный lookbehind и вполне совершенствуется. –  Ingo Karkat 21.09.2013, 18:09
  • 3
    +1. Интересная вещь, переменная ширина lookbehind не поддерживается в Perl! Я никогда не думал, что Perl regex механизм будет когда-либо испытывать недостаток в чем-то другом, что механизмы имеют. –  Joseph R. 21.09.2013, 23:10

Принятие Вас имеет только одно возникновение pattern прежде =, можно сделать это на двух шагах:

:%s/pattern/saturn/g
:%s/saturn\(.\{-}=\)/pattern\1/

\{-} сообщает . соответствовать лениво (иначе нежадно).

Объяснение

Этот первый шаг заменяет все случаи pattern saturn следующий шаг затем ищет слово saturn прежде = и замены это с pattern.

Внимание

Это принимает отдельное проявление = на каждой строке.

Лучший путь (только принимает сингл = на строку)

Можно сделать это с рекурсивным макросом:

qaqqa:%s/\(=.\{-}\)pattern/\1saturn/@aq@a

Это заменяет отдельным проявлением pattern после = с saturn. При хранении как макрос и рекурсивном вызове это будет продолжать работать над файлом, пока нет ничего для замены. Это - hackish, но это работает.

См. также

5
27.01.2020, 20:18
  • 1
    Это заменит все случаи шаблона после =? Как? Я не знаю, сколькими будет заранее. –  user13107 19.09.2013, 21:31
  • 2
    @user13107 Мой исходный ответ заменил только единственный экземпляр pattern после =. См. обновленный ответ. –  Joseph R. 19.09.2013, 21:41
  • 3
    Спасибо помощник, который был умен, к сожалению, существует неизвестное количество их прежде = :( argh –  user13107 19.09.2013, 21:47
  • 4
    @user13107 у меня есть взлом для работы вокруг этого. Отправит, когда у меня будет время. –  Joseph R. 19.09.2013, 22:12
  • 5
    это также предполагает что строка saturn не находится в тексте. вероятно, верный, но я был бы склонен использовать что-то намного более неясное/уникальное в качестве временной строки замены - myhamsterlivesonsaturn, возможно, :) –  cas 20.09.2013, 06:24

Теги

Похожие вопросы