Попробуйте:
awk '{gsub(/%[^A-Ga-gm-np-s]+/, "%")} 1' .annex/file.c
Пример
Рассмотрим этот входной файл:
$ cat file.c
fprintf(stdout,"%-20s %0.h2d",a,b)
fprintf(stderr,"%.3f",c)
Давайте запустим нашу команду:
$ awk '{gsub(/%[^A-Ga-gm-np-s]+/, "%")} 1' file.c
fprintf(stdout,"%s %d",a,b)
fprintf(stderr,"%f",c)
Как это работает
gsub(/%[^A-Ga-gm-np-s]+/, "%")
ищет любую строку, которая соответствует %
, за которой следуют символы, которые не входят ни в один из диапазонов A-G
, a-g
, m-n
или p-s
, и заменяет ее просто %
.
Замена только n-го вхождения
Если вы хотите заменить только n-е вхождение, попробуйте:
sed -E 'H;1h;$!d;x; s/%[^A-Ga-gm-np-s]+/%/'"$n"
Чтобы заменить, например, второе вхождение, используйте:
$ n=2; sed -E 'H;1h;$!d;x; s/%[^A-Ga-gm-np-s]+/%/'"$n" file.c
fprintf(stdout,"%-20s %d",a,b)
fprintf(stderr,"%.3f",c)
Для замены третьего:
$ n=3; sed -E 'H;1h;$!d;x; s/%[^A-Ga-gm-np-s]+/%/'"$n" file.c
fprintf(stdout,"%-20s %0.h2d",a,b)
fprintf(stderr,"%f",c)
Вы можете использовать любое значение для n
, которое вам нравится.
Как это работает
-E
говорит sed использовать расширенные регулярные выражения (тип по умолчанию для awk), а не базовые регулярные выражения.
H;1h;$!d;x;
говорит sed читать файл в пространство шаблона.
Эта серия команд читает весь файл. Вероятно, проще всего думать об этом как о идиоме. Если вы действительно хотите узнать подробности:
H
- добавить текущую строку в качестве пробела
1h
- Если это первая строка, перезаписать пробел
с этим
$!d
- Если это не последняя строка, удалить пробел
и перейти к следующей строке.
x
- обмен удержанием и шаблоном для размещения всего файла
шаблон пространства
's/%[^A-Ga-gm-np-s]+/%/'"$n"
указывает sed заменить n-ное вхождение шаблона.