Как я могу обнаружить разрывы строк DOS в файле?

У меня куча файлов. Некоторые из них являются окончаниями строк Unix, многие - DOS. Я хотел бы протестировать каждый файл, чтобы увидеть, отформатирован ли он, прежде чем переключать концы строк.

Как мне это сделать? Есть ли флаг, который я могу проверить? Что-то похожее?


person chiggsy    schedule 09.05.2010    source источник
comment
Тот же вопрос, что и stackoverflow.com/questions/121392/ ​​ (кроме того, что помечено как 'python' :-)   -  person Jonik    schedule 09.05.2010


Ответы (7)


Вы можете искать в строке \r\n. Это конец строки в стиле DOS.

РЕДАКТИРОВАТЬ: взгляните на это

person nc3b    schedule 09.05.2010
comment
Да, это правильный путь. Нет флага или чего-то подобного. - person Jonik; 09.05.2010
comment
Технически вы ищете "\r\x0A". Большинство компиляторов используют перевод строки для '\n', но не обязательно иметь это конкретное значение. - person Adrian McCarthy; 10.05.2010

Python может автоматически определять, какое соглашение о новой строке используется в файле, благодаря «универсальному режиму новой строки» (U), и вы можете получить доступ к предположению Python через атрибут newlines файловых объектов:

f = open('myfile.txt', 'U')
f.readline()  # Reads a line
# The following now contains the newline ending of the first line:
# It can be "\r\n" (Windows), "\n" (Unix), "\r" (Mac OS pre-OS X).
# If no newline is found, it contains None.
print repr(f.newlines)

Это дает окончание новой строки первой строки (Unix, DOS и т. Д.), Если таковая имеется.

Как заметил Джон М., если случайно у вас есть патологический файл, в котором используется более одного кодирования новой строки, f.newlines - это кортеж со всеми кодировками новой строки, найденными до сих пор, после прочтения большого количества строк.

Ссылка: http://docs.python.org/2/library/functions.html#open

Если вы просто хотите преобразовать файл, вы можете просто сделать:

with open('myfile.txt', 'U') as infile:
    text = infile.read()  # Automatic ("Universal read") conversion of newlines to "\n"
with open('myfile.txt', 'w') as outfile:
    outfile.write(text)  # Writes newlines for the platform running the program
person Eric O Lebigot    schedule 10.05.2010
comment
-1 Это называется newlines (множественное число) и это не кодировка. Вы показали, как найти то, что (если есть) завершает первую строку (если есть). Ваш комментарий неверен: он не включает случай, когда первая и единственная строка не заканчивается (и поэтому newlines относится к None). Кроме того, предполагается, что все линии завершаются одинаково. Неизвестны конкатенации файлов с разными окончаниями строк. В приложении OP по стандартизации в конце одной строки ему нужно будет прочитать ВСЕ входной файл (и ВСЕ документы, особенно там, где упоминается tuple). - person John Machin; 10.05.2010
comment
@John: Давай: -1 за ответ, в котором упоминается полезный newlines, но только с опечаткой? Или для патологических файлов, составленных из файлов с разными условными обозначениями новой строки? В оригинальном плакате упоминались файлы из Unix или DOS, а не такие странные файлы! - person Eric O Lebigot; 10.05.2010
comment
@John: Интересна ваша информация о том, что f.newlines возвращает кортеж в случае смешанного соглашения о новой строке. Добавил в ответ. - person Eric O Lebigot; 10.05.2010
comment
Я поддержал это. Я был для меня полезным ответом. @John делает очень хорошее замечание относительно угловых случаев. - person chiggsy; 11.05.2010
comment
Спасибо! В ответе я процитировал угловой случай Джона, потому что он мне тоже показался интересным. :) - person Eric O Lebigot; 11.05.2010
comment
Атрибут newlines файловых объектов поступает из io.TextIOBase (Python 3): строка, кортеж строк или None, указывающий на переведенные на данный момент новые строки. В зависимости от реализации и начальных флагов конструктора это может быть недоступно. - person handle; 26.07.2016
comment
Интересно, что официальная ссылка, приведенная в ответе, указывает, что newlines всегда доступен, хотя ... - person Eric O Lebigot; 23.08.2018

(Только для Python 2 только :) Если вы просто хотите читать текстовые файлы в формате DOS или Unix, это работает:

print open('myfile.txt', 'U').read()

То есть "универсальный" читатель файлов Python будет автоматически использовать разные маркеры конца строки, переводя их в "\ n".

http://docs.python.org/library/functions.html#open

(Спасибо, ручка!)

person johntellsall    schedule 09.05.2010
comment
Что ж, я хочу отредактировать их в vim. Я хотел бы изменить окончание этой строки один раз и зафиксировать его, по сравнению с файлом. - person chiggsy; 10.05.2010
comment
Это деструктивно изменит DOS CRLF на Unix LF для всех файлов в текущем каталоге: perl -p0i -e 's / \ r \ n / \ n / g' * Я набирал это столько раз, что мои пальцы запомнили его: ) - person johntellsall; 11.05.2010
comment
@chiggsy установите пакет dos2unix и скорее запустите команду dos2unix для файлов. - person nos; 07.04.2014
comment
Режим U устарел в Python 3. - person handle; 26.07.2016

Как полный новичок в Python и просто для удовольствия, я попытался найти какой-нибудь минималистичный способ проверить это для одного файла. Кажется, это работает:

if "\r\n" in open("/path/file.txt","rb").read():
    print "DOS line endings found"

Изменить: упрощено в соответствии с комментарием Джона Мачина (не нужно использовать регулярные выражения).

person Jonik    schedule 09.05.2010
comment
Разве вы не должны открывать файл с помощью rb? - person President James K. Polk; 09.05.2010
comment
Хм, моя первая мысль была нет, потому что мы имеем дело с текстовыми файлами ... Но вы имеете в виду это: по умолчанию используется текстовый режим, который может преобразовывать символы '\ n' в платформенно-зависимое представление о записи и обратном чтении. (docs.python.org/library/functions.html#open)? Я не знал о таких преобразованиях - возможно, действительно стоит использовать rb, чтобы это работало и в системах, отличных от Unix. - person Jonik; 10.05.2010
comment
re.search() не минималистичен; это OVERKILL; используйте "\r\n" in open(...).read(). Нет, может быть, об использовании "rb"; это обязательно. - person John Machin; 10.05.2010

Разрывы строк в dos - \r\n, только unix \n. Так что просто ищите \r\n.

person Femaref    schedule 09.05.2010

Используя grep и bash:

grep -c -m 1 $'\r$' file

echo $'\r\n\r\n' | grep -c $'\r$'     # test

echo $'\r\n\r\n' | grep -c -m 1 $'\r$'  
person shallo    schedule 10.05.2010

Вы можете использовать следующую функцию (которая должна работать в Python 2 и Python 3), чтобы получить представление новой строки, используемое в существующем текстовом файле. Признаны все три возможных вида. Функция читает файл только до первого символа новой строки. Это быстрее и требует меньше памяти, когда у вас есть большие текстовые файлы, но он не обнаруживает смешанные окончания новой строки.

В Python 3 вы можете передать вывод этой функции в параметр newline функции open при записи файла. Таким образом, вы можете изменить контекст текстового файла без изменения его представления новой строки.

def get_newline(filename):
    with open(filename, "rb") as f:
        while True:
            c = f.read(1)
            if not c or c == b'\n':
                break
            if c == b'\r':
                if f.read(1) == b'\n':
                    return '\r\n'
                return '\r'
    return '\n'
person Cito    schedule 30.04.2019