Мы не можем быть полностью уверены в вариабельности частей aaa
или bcd
;предположительно, каждый из них может быть почти чем угодно.
Вам, вероятно, следует искать:
- последовательность из одного или нескольких символов, не являющихся точкой с запятой, без точки с запятой, за которыми следует двоеточие,
- с одним или несколькими повторениями:
- серия из одного или нескольких символов, не являющихся точкой с запятой, не точка с запятой, за которой следует точка с запятой
Это составляет единицу, которую вы хотите сопоставить.
/[^:;]+:([^:;]+;)+/
Таким образом, вы можете заменить то, что было найдено, тем же, после которого следует новая строка, а затем распечатать результат.Единственный трюк - избегать лишних переводов строки.
Пример сценария:
{
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()
, поскольку за ним не следует двоеточие или точка с запятой.