Intereting Posts
Mint 15 Высокие темпы на e-450, вентилятор, казалось бы, не реагирует Как изменить дату изменения каталога при изменении файлов из этого каталога? Сценарий Bash для копирования текста, который в настоящее время введен для подсказки Несколько терминалов одновременно без сервера X MariaDB: создание и предоставление нового пользователя с помощью плагина unix sockets (без пароля) Как найти и фильтровать определенный столбец в CSV-файле? В чем разница между параметрами -H и -L chown? Как проверить, была ли ISO записана на мой USB-накопитель без ошибок? Использование Crontab -e с нестандартным редактором с ограниченной оболочкой (не экспортировать переменную или запустить редактор) ZFS: отправка / получение со скользящими моментальными снимками Показать текст замены псевдонима в файле .bash_history Настройка вторичной среды Vim Как я могу найти объем памяти, потребляемый процессом? Файл Raspbian / etc / network / interfaces отсутствует в ArchLinux Избегайте необычных символов в именах файлов с помощью `find. -printf "% p \ n" `

Как пропустить файл в sed, если он содержит регулярное выражение?

В настоящее время я использую следующую упрощенную команду для удаления конечных пробелов и добавления новой строки в конец файла, где это необходимо:

find . -type f -exec sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' {} \+ 

Как вы быстро увидите, это имеет две проблемы: он изменит двоичные файлы и добавит новую строку в конец файлов с разделителями строк . Эти изменения легко отменить или пропустить при совершении в git gui или т. П., Но я хотел бы свести к минимуму количество возвращающихся данных. С этой целью:

Есть ли способ пропустить весь файл, если какая-либо строка соответствует регулярному выражению в sed ?

* Я знаю, что могут быть двоичные файлы без ␀ символов, и могут быть файлы с намеренно смешанными переводами строк или ␀s. Но я ищу решение, требующее минимального вмешательства человека. Я мог бы, вероятно, перечислять все расширения файлов, над которыми я хотел бы работать, но это был бы очень длинный список, который нужно было бы постоянно проверять, и из-за конфликтов имен все равно было бы возможно, что бинарные файлы проскальзывают.

Сложное обходное решение :

 while IFS= read -r -d '' -u 9 do if [[ "$(file -bs --mime-type -- "$REPLY")" = text/* ]] then sed -i -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' -- "$REPLY" else echo "Skipping $REPLY" >&2 fi done 9< <(find . -type f -print0) 

Если вы доверяете точке зрения git на то, что является двоичным файлом или нет, вы можете использовать git grep для получения списка не двоичных файлов. Предполагая, что t.cpp является текстовым файлом, а ls является двоичным, оба отмечены:

 $ ls t.cpp ls $ git grep -I --name-only -e '' t.cpp 

Опция -I означает:

-I
Не сопоставляйте шаблон в двоичных файлах.

Чтобы объединить это с выражением sed :

 $ git grep -I --name-only -z -e '' | \ xargs -0 sed -i.bk -e 's/[ \t]\+\(\r\?\)$/\1/;$a\' 

( -z / xargs -0 чтобы помочь со странными именами файлов.)

--cached страницу git grep man для других полезных опций – --no-index или --cached может помочь в зависимости от того, какой набор файлов вы хотите использовать.

Вот скрипт Perl, который выполняет итерации по своим аргументам (которые должны быть именами файлов) и добавляет новую строку для каждого файла, который не заканчивается в новой строке. Файлы, содержащие нулевой байт, пропускаются. Файлы, которые уже заканчиваются в новой строке, не изменяются. Файлы, содержащие CR, получают CRLF, другие получают только LF. Непроверенные.

 #!/usr/bin/env perl foreach my $f (@ARGV) { open F, "<", $f or die; my $last = undef; my $cr = 0; while (<>) {if (/\0/) {undef $last; break} $last = $_; ++$cr if /\r$/} close F; if (defined $last && $last !~ /\n\Z/) { open F, ">>", $f or die; print($cr ? "\r\n" : "\n"); close F or die; } } 

Есть ли способ пропустить весь файл, если какая-либо строка соответствует регулярному выражению в sed?

Да, есть.

 # test case for skipping file if a sed regex match succeeds echo 'Hello, world!' > hello_world.txt cat hello_world.txt ls -li hello_world.txt sed -i -e '/.*Hello.*/{q;}; s/world/WORLD/g' hello_world.txt # skips file sed -i -e '/.*HeLLo.*/{q;}; s/world/WORLD/g' hello_world.txt