Этот сценарий sed преобразует ваши тестовые данные, но потребует изменения, если ваши файлы содержат более одного блока, использующего / namespace, или если пробел не идентичен.
# match using lines
/^using/{
s/^/ / # prepend whitespace
H # append to hold
d # don't print (yet)
}
# match namespace lines
/^namespace/{
G # append the using block after namespace line
# loop while we can strip a namespace name from a using line
:a
s/\(\([^ ]*\) {.*using \)\2\./\1/
ta
# read in next line and delete it if empty
N
s/\n\n/\n/g
}
# implicit print
Вторая команда s///
выглядитдля имени, которое предшествует {
(т. е. \([^ ]*\)
), за которым следует строка using
с тем же именем, за которым следует точка (т. е. \2\.
). Полное совпадение, кроме конечного \2\.
, доступно как \1
из-за начального набора \(
... \)
и заменяет исходный текст.
Опираясь на ответ @ Jotne, эквивалентная версия awk выглядит следующим образом:
/^using/ {
# store using lines, along with a prepended space
a[++i] = " " $0
next
}
/^namespace/ {
print
# strip namespace name from using lines, then print
r = " " $2 "[.]"
for(i in a) {
sub(r, " ", a[i])
print a[i]
}
# delete subsequent line if it is blank
getline
if ($0) print
next
}
# print every other line
1
Здесь регулярное выражение (r
) ищет пробел, за которым следует имя пространства имен (оно должнобыть $2
в строке пространства имен), за которым следует точка. sub()
заменяет все вхождения этого регулярного выражения в сохраненных строках, используя только один пробел.