2010-04-05 3 views
1

Я читаю текстовый файл через CGI в perl и замечаю, что когда файл сохраняется в textEdit в маке, разделитель строк распознается, но когда я загружаю CSV, который экспортируется прямо из excel, это не так. Я предполагаю, что это проблема \ n vs. \ r, но мне показалось, что я не знаю, как указать, что я хотел бы использовать токен терминатора линии, если бы я не хотел, чтобы он искал по умолчанию.есть ли способ обозначить разделитель токенов в файловом считывателе Perl?

+1

Обратите внимание: если вы читаете CSV, вы обязательно захотите использовать модуль, например [Text :: CSV] (http://search.cpan.org/perldoc?Text::CSV), с помощью ' Вместо этого установлен текст :: CSV_XS'. Не пытайтесь изобретать колесо чтения CSV ... в первый раз это достаточно сложно! –

ответ

4

Да. Вы захотите переписать значение $/. От perlvar

$/

Входной разделитель записей, символ новой строки по умолчанию. Это влияет на идею Перла о том, что такое «линия». Работает как переменная RS awk, включая обработку пустых строк в качестве терминатора, если задана нулевая строка. (Пустая строка не может содержать пробелов или вкладок.) Вы можете установить ее в многосимвольную строку для соответствия терминатору с несколькими символами или undef для чтения в конце файла. Установка его в «\ n \ n» означает нечто немного отличное от установки на «», если файл содержит последовательные пустые строки. Установка в «" будет обрабатывать две или более последовательных пустых строк как одну пустую строку. Установка в «\ n \ n» будет вслепую предполагать, что следующий входной символ относится к следующему абзацу, даже если это новая строка. (Мнемоника:/разграничивает границы строки при цитировании поэзии.)

local $/;   # enable "slurp" mode 
local $_ = <FH>; # whole file now here 
s/\n[ \t]+/ /g; 

Помните: значение $/является строка, а не регулярное выражение. awk должно быть лучше для чего-то. :-)

Установка $/для ссылки на целое число, скаляр, содержащий целое число, или скаляр, преобразуемый в целое число, будет пытаться читать записи вместо строк, причем максимальный размер записи является целым числом. Таким образом:

local $/ = \32768; # or \"32768", or \$var_containing_32768 
open my $fh, "<", $myfile or die $!; 
local $_ = <$fh>; 

будет читать запись не более 32768 байт из ФАЙЛА. Если вы не читаете из файла, ориентированного на запись (или у вашей ОС нет файлов, ориентированных на запись), тогда вы, вероятно, получите полный кусок данных при каждом чтении. Если запись больше размера записи, которую вы установили, вы снова получите запись. Попытка установить размер записи до нуля или меньше приведет к чтению в целом (остальной части) файла.

На VMS записи записываются с эквивалентом sysread, поэтому лучше не смешивать записи и записи без записи в одном файле. (Это вряд ли будет проблемой, потому что любой файл, который вы хотите прочитать в режиме записи, вероятно, непригоден в линейном режиме.) Системы, отличные от VMS, выполняют обычный ввод-вывод, поэтому безопасно смешивать записи и записи без записи файла.

См. Также «Новые строки» в perlport. Также см. $ ..

+0

спасибо! Я понимаю, что это глупый вопрос, но спросите, на всякий случай ... настройка ограничена только для этого скрипта, правильно? Это не повлияет на поведение других скриптов? –

+0

@ Dr.Dredel => ключевое слово 'local' ограничивает масштаб ваших изменений глобальным. Правила определения местоположения для 'local' такие же, как' my', поэтому локализация завершится в конце текущего блока. Очень важно отметить, что любые переменные, которые локализованы, будут иметь новое значение в коде, вызываемом из области локализации. Пока ваша локализация небольшая 'my $ file = do {local $ /; <$fh>} 'тогда вам не о чем беспокоиться. И все изменения, конечно, теряются, когда скрипт заканчивается, даже если вы не использовали локальный. –

2

переменная имеет несколько названий:

  • $/
  • $RS
  • $INPUT_RECORD_SEPARATOR

Для более длинных имен, вам необходимо:

use English; 

Не забудьте тщательно локализовать:

{ 
local($/) = "\r\n"; 
...code to read... 
} 
1

Если вы читаете в файл с терминаторами линии CRLF, вы можете открыть его с помощью CRLF дисциплины, или установить binmode ручки сделать автоматический перевод.

open my $fh, '<:crlf', 'the_csv_file.csv' or die "Oh noes $!"; 

Это будет прозрачно преобразовать \r\n последовательности в \n последовательности.

Вы также можете применить этот перевод к существующей ручке, выполнив:

binmode($fh, ':crlf'); 

:crlf режима обычно по умолчанию в среде Win32 Perl и работает очень хорошо на практике.

Смежные вопросы