Ошибка в команде wc при чтении количества строк в файле

Ошибка в команде wc при чтении количества строк в файле

Я использовал wc -lдля проверки количества строк, существующих в моих файлах. Это всегда работало нормально, но не в этот раз.

У меня есть 120 больших файлов, в каждом из которых должно быть не менее двух строк. Я только что выполнил некоторую работу по редактированию текста в этих файлах, чтобы удалить и добавить новые строки. Я пытался проверить окончательное количество строк, используя wc -l *как обычно. Вывод показал, что большинство файлов имели только одну строку.

Я открыл один из файлов (который показал из результата команды, что в нем была только одна строка) с помощью vimи я вижу, что в нем было ровно 2 строки. Выйдите vimи проверьте снова с помощью wc -l, номер строки для этого файла затем появился как 2.

Кто-нибудь знает, что здесь произошло? И как мне решить эту проблему, вместо того, чтобы открывать все 120 файлов с помощью vim?

PS: Последняя строка моих файлов не была пустой.

решение1

Распространенная реализация GNU wcговорит:

«wc» подсчитывает количество байтов, символов, слов, разделенных пробелами,
и символов новой строки в каждом указанном ФАЙЛЕ или стандартном вводе, если ничего не указано или для ФАЙЛА «-».

поэтому если в файле нет завершающего символа новой строки, часть "строки" вывода wcбудет на единицу меньше ожидаемого. Например, следующий код выведет 1

printf 'hello\nworld' | wc -l 

OP подтвердил в комментариях, что vim сообщает об отсутствии последней новой строки. Простое исправление, если известно, что во всех файлах есть эта проблема, это

 for f in *
 do
     echo >> "$f"
 done

для добавления новой строки к каждому файлу.

Условный способ добавления новой строки в конец всех файлов, если она отсутствует, — использовать sed.

sed -s -i '$s/$/\n/;P;d' *

использует некоторые расширения gnu, -sчтобы обрабатывать каждый файл отдельно, -iчтобы делать редактирование на месте и разрешать \nпредставлять новую строку. Сама программа sed говорит в последней строке каждого файла добавить новую строку, и для каждой строки вывести до первой новой строки и перейти на следующую строку.

решение2

Это не совсем ответ, но я поделюсь небольшим персональным инструментом, который я часто использую для нормализации текстовых файлов (txtnorm):

#!/usr/bin/perl -spi
our($s);
s/\n\r|\r\n|\n|\r/\n/g;                 ## normalize \n
s/^(\xFF\xFE|\xFE\xFF|\xEF\xBB\xBF)//;  ## remove BOM !
s/(?<=.)\z/\n/;                         ## ensure newline at eof

if($s){ s/\xC2\xA0/ /g }                ## -s non breaking spaces-> " "

txtnorm *.txtнормализует конец строк, обеспечивает перевод строки в конце файла, удаляет BOM и (с -s) может нормализовать неразрывные пробелы.

Обязательно используйте его ТОЛЬКО для текстовых файлов.

Связанный контент