[РЕДАКТИРОВАТЬ: Исправлено обрезание пробелов]
[РЕДАКТИРОВАТЬ # 2: убрать конечные пустые строки из конца файла]
perl -i.bak -pe 'if (defined $x && /\S/) { print $x; $x = ""; } $x .= "\n" x chomp; s/\s*?$//; 1 while s/^(\t*) /$1\t/; if (eof) { print "\n"; $x = ""; }' **/*(.)
Это удаляет завершающие пустые строки из файла, но оставляет ровно одну \n
в конце файла. Большинство инструментов ожидают этого, и в большинстве редакторов это не будет отображаться как пустая строка. Однако, если вы хотите удалить этот самый последний \n
, просто удалите часть print "\n";
из команды.
Команда работает путем "сохранения" \n
символов до тех пор, пока не будет видна строка, содержащая непустой символ - затем она печатает их все перед обработкой этой строки.
Удалите .bak
, чтобы избежать создания резервных копий исходных файлов (используйте на свой страх и риск!)
\s*?
соответствует нулю или более пробельных символов без жадности, включая \r
, который является первым символом \r\n
синтаксиса перевода строки DOS. В Perl $
соответствует либо в конце строки, либо непосредственно перед финальным \n
, что в сочетании с тем фактом, что *?
соответствует не жадным образом (сначала выполняется поиск по ширине 0, затем 1- соответствие ширины и т. д.) это делает правильно.
1 while s/^(\t*) /$1\t/
- это просто цикл, который многократно заменяет любые строки, начинающиеся с любого количества вкладок, за которыми следуют 4 пробела, на одну вкладку больше, чем было до тех пор, пока это уже невозможно. Так что это будет работать, даже если некоторые строки уже частично были преобразованы во вкладки, при условии, что все символы \t
начинаются со столбца, кратного 4.
Я раньше не видел синтаксис **/*(.)
, предположительно, это расширение zsh
? Если он работал с sed
, он будет работать с perl
.