phd_ru: (Linux)
[personal profile] phd_ru
У меня регулярно встаёт задача "найти файлы, в которых N пустых строк подряд и заменить их на M пустых строк, M обычно < N". Сегодня у меня эта задача возникла как часть задачи "удалить в файлах группу строк от __version__ до __copyright__ и оставшиеся пустые строки убрать", поэтому я выкрутился так:
grep -FIlr __version__ . >.list
for f in `cat .list`; do sed -e '/__version__/,/__copyright__/d' $f >.tmp && cp .tmp $f || break; done
for f in `cat .list`; do vim -X -c '%s/\n\n\n\n\+/\r\r\r/' -c up -c q $f || break; done
rm .list .tmp

Но в общем виде я эту задачу решать не умею: grep и sed не очень понимают \n. И vim — не самый подходящий инструмент для неинтерактивной обработки файлов. Подскажите, как это правильно делать?

Upd. grep -Pz помогает; т.е. воспринять весь файл, как одну строку, и в ней искать с помощью перловых регэкспов:
grep -Plrz --exclude-dir=.git --exclude='*.py[co]' '\n\n\n' .

Чем заменить пустые строки — вопрос остаётся.

Другой вариант — vimgrep, но у vimgrep небогатые возможности выбора файлов для поиска. Хорошо, если я ищу только по питоновским файлам:
:vimgrep '\n\n\n\+' **/*.py
Но мне часто приходится искать по директориям, в которых полно файлов без расширений — shell-скрипты, Makefile'ы и т.д. А ** залезет и в файлы, куда залезать не надо — в директории .hg/.git/.svn, в питоновский байткод *.py[co], а это лишнее.

Кстати, мой второй цикл for можно оптимизировать:
vim -X -c ':argdo! %s/\n\n\n\+/\r\r\r/' -c xall `cat .list`

June 2025

S M T W T F S
12 3 45 67
89101112 1314
15161718192021
2223 2425 26 27 28
29 30     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 3rd, 2025 06:30 am
Powered by Dreamwidth Studios