Немного ужасной 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"'
Я записал это, поскольку полевой порядок может варьироваться по различным полям, но профиль всегда является последним. В случае, если порядок всегда является тем же, это было бы немного легче.
Можно использовать специальный атом \@<=
утверждать соответствие прежде (=.*
сделать его где угодно прежде в той строке):
:%s/\(=.*\)\@<=pattern/saturn/g
Принятие Вас имеет только одно возникновение pattern
прежде =
, можно сделать это на двух шагах:
:%s/pattern/saturn/g
:%s/saturn\(.\{-}=\)/pattern\1/
\{-}
сообщает .
соответствовать лениво (иначе нежадно).
Объяснение
Этот первый шаг заменяет все случаи pattern
saturn
следующий шаг затем ищет слово saturn
прежде =
и замены это с pattern
.
Внимание
Это принимает отдельное проявление =
на каждой строке.
Лучший путь (только принимает сингл =
на строку)
Можно сделать это с рекурсивным макросом:
qaqqa:%s/\(=.\{-}\)pattern/\1saturn/@aq@a
Это заменяет отдельным проявлением pattern
после =
с saturn
. При хранении как макрос и рекурсивном вызове это будет продолжать работать над файлом, пока нет ничего для замены. Это - hackish, но это работает.
См. также
pattern
после =
. См. обновленный ответ.
– Joseph R.
19.09.2013, 21:41
=
:( argh
– user13107
19.09.2013, 21:47
saturn
не находится в тексте. вероятно, верный, но я был бы склонен использовать что-то намного более неясное/уникальное в качестве временной строки замены - myhamsterlivesonsaturn
, возможно, :)
– cas
20.09.2013, 06:24
:help /\@<=
(Я не могу объяснить это лучше), но не плохо себя чувствуйте, когда Вы не получаете его сначала. Это назвало положительный lookbehind и вполне совершенствуется. – Ingo Karkat 21.09.2013, 18:09