Мы не можем быть уверены в изменчивости частей aaa
или bcd
; предположительно, каждый из них может быть почти чем угодно.
Вероятно, вам следует искать:
- последовательность из одного или нескольких символов без двоеточия и точки с запятой, за которыми следует двоеточие,
- with one or more repeats of:
- a series of one or more non-colon, non-semicolon characters followed by a semi-colon
Это составляет единицу, которую вы хотите сопоставить.
/[^:;]+:([^:;]+;)+/
При этом вы можете заменить то, что было найдено, на то же самое, за которым следует новая строка, а затем распечатать результат. Единственная хитрость — избегать лишних строк новой строки.
Пример скрипта:
{
echo "aaa: bcd;bcd;bcddd;aaa:bcd;bcd;bcd;"
echo "aaz: xcd;ycd;bczdd;baa:bed;bid;bud;"
} |
awk '{ gsub(/[^:;]+:([^:;]+;)+/, "&\n"); sub(/\n+$/, ""); print }'
Пример вывода
aaa: bcd;bcd;bcddd;
aaa:bcd;bcd;bcd;
aaz: xcd;ycd;bczdd;
baa:bed;bid;bud;
Перефразируя вопрос в комментарии:
Почему регулярное выражение не включает символы перед двоеточием (именно для этого оно и предназначено, но я не понимаю почему)? Я не понимаю, что «ломает» или завершает регулярное выражение.
Как я пытался объяснить выше, вы ищете то, что мы можем назвать «словами», то есть последовательности символов, которые не являются ни двоеточием, ни точкой с запятой. В регулярном выражении это [^:;]+
, что означает один или несколько (+
) класса отрицательных символов, один или несколько символов без двоеточия и точки с запятой.
Предположим, что пробелы в регулярном выражении не имеют значения. Мы можем разделить регулярное выражение следующим образом:
/ [^:;]+ : ( [^:;]+ ; ) + /
Косые черты просто отмечают концы, конечно. Первый кластер — это слово; тогда есть двоеточие. Затем идет группа, заключенная в круглые скобки, помеченная +
в конце. Это означает, что содержимое группы должно встречаться хотя бы один раз и может встречаться сколько угодно раз. Что внутри группы? Ну, слово, за которым следует точка с запятой. Это не обязательно должно быть одно и то же слово каждый раз, но там должно быть слово. Если что-то может произойти ноль или более раз, то вы, конечно, используете *
вместо +
.
Ключом к остановке регулярных выражений является то, что aaa:
в середине первой строки не состоит из слова, за которым следует точка с запятой; это слово, за которым следует двоеточие. Таким образом, регулярное выражение должно быть остановлено до этого, потому что aaa:
не соответствует группе. Таким образом, gsub()
находит первую последовательность и заменяет этот текст тем же материалом и новой строкой (конечно, это "&\n"
). Затем он (gsub()
) возобновляет поиск сразу после окончания замещающего материала, и, о чудо, есть слово, за которым следует двоеточие, и несколько слов, за которыми следует точка с запятой, так что есть второе совпадение, которое нужно заменить исходным материалом, плюс новая линия.
Я думаю, что $0
должен содержать новую строку в конце строки. Поэтому без sub()
для удаления завершающей новой строки print
(косвенно из $0
с новой строкой) генерировало пустую строку, которую я не хотел выводить, поэтому я удалил лишние символы новой строки. Новая строка в конце $0
не будет соответствовать gsub()
, поскольку за ней не следует двоеточие или точка с запятой.
person
Jonathan Leffler
schedule
29.03.2012