Почему 'chomp' не удаляет переводы строк в Windows XP с помощью Eclipse и Cygwin Perl? - PullRequest
2 голосов
/ 05 октября 2009

Я использую Windows XP, Eclipse 3.2 с EPIC и Cygwin для моего интерпретатора Perl, и я получаю неожиданный результат.

К вашему сведению ... Когда я запускаю его в своем дистрибутиве Ubuntu ( VMware , тот же компьютер), я получаю ожидаемые результаты. Почему?

############ CODE: #############

use warnings;
use strict;

my $test = "test";
my $input = <STDIN>;

print length $test, " ", length $input, "\n";

chomp $input;

print "|$test| |$input| \n";    #The bars indicate white space, new line, etc...

print length $test, " ", length $input, "\n";

if ($test eq $input) {
    print "TIME TO QUIT";
}

Результаты в Windows XP:

test           <-- My input
4 6            <-- Lengths printed before chomp
|test| |test   <-- Print the variables after chomp
|              <-- There is still a new line there
4 5            <-- Lengths after the initial chomp

Ответы [ 3 ]

6 голосов
/ 05 октября 2009

Учитывая, что Windows XP фигурирует в проблеме, разница должна быть связана с обработкой CRLF (возврат каретки, перевод строки). chomp удаляет, кажется, LF, но не CR; печать переводит CR в CR LF.

Документ Perl для chomp говорит, что если вы правильно установили EOL для Windows ($/ = "\r\n";), то chomp должен все делать правильно:

$/ = "\r\n";
$test = "test\r\n";
print "<<$test>>\n";
chomp $test;
print "<<$test>>\n";

Шестнадцатеричный дамп вывода, который дает:

0x0000: 3C 3C 74 65 73 74 0D 0A 3E 3E 0A 3C 3C 74 65 73   <<test..>>.<<tes
0x0010: 74 3E 3E 0A                                       t>>.
0x0014:

Я не уверен, почему $/ не устанавливается автоматически - это может быть Cygwin, запутывающий вещи (притворяясь, что он слишком успешно работает в Unix).

4 голосов
/ 05 октября 2009

Вот как удалить трейлинг \r\n или \n (в зависимости от того, что находится в конце):

$input =~ s@\r?\n\Z(?!\n)@@;

Другой вариант - сделать

binmode(STDIN, ':crlf')

прежде чем читать что-либо из STDIN. Это преобразует конечный \r\n в \n, который можно удалить с помощью chomp. Это также будет работать, даже если ваш ввод содержит только \n. См. Документацию по PerlIO для получения дополнительной информации.

4 голосов
/ 05 октября 2009

Исходя из длины, я бы сказал, что вы получаете входную строку в виде:

test<cr><lf>

, где <cr> и <lf> - коды ASCII 0x13 и 0x10 соответственно.

Когда вы сжимаете его, он удаляет <lf>, но оставляет <cr> там.

Это почти наверняка проблема взаимодействия между Eclipse, Cygwin и Windows, не согласная с тем, какой должна быть последовательность символов конца строки. Я не смог воспроизвести вашу проблему только с Perl / Cygwin или Perl / Windows, но эта команда дает похожие результаты (в Cygwin):

echo 'test^M' | perl qq.pl | sed 's/^M/\n/g'

(qq.pl - это ваш скрипт, а "^M" - это фактический CTRL-M). Вот вывод в текстовом виде:

4 6
|test| |test
|
4 5

и восьмеричный дамп:

0000000 2034 0a36 747c 7365 7c74 7c20 6574 7473
          4       6  \n   |   t   e   s   t   |       |   t   e   s   t
        064 040 066 012 174 164 145 163 164 174 040 174 164 145 163 164
0000020 7c0a 340a 3520 000a
         \n   |  \n   4       5  \n  \0
        012 174 012 064 040 065 012 000
0000027

Итак, я бы сказал, что ваш ввод включает в себя <cr> и <lf>, а печать переводит <cr> в <lf> (или просто делает одно и то же для обоих из них).

Если вам нужен обходной путь для вашей среды, вы можете заменить строку chomp на:

$input =~ s/\r?\n$//;

как в:

use warnings;
use strict;
my $test = "test";
my $input = <STDIN>;
print length $test ," ",length $input,"\n";
$input =~ s/\r?\n$//;
print "|$test| |$input|\n";
print length $test," ",length $input,"\n";
if ($test eq $input) {
    print "TIME TO QUIT";
}

, который работает на Cygwin для тестовых данных, которые я использовал (конечно, проверьте это для вашей собственной ситуации), но вы можете обнаружить, что можете решить ее лучше, используя инструменты, которые все согласовывают последовательность конца строки (например, Perl для Windows, а не Cygwin, может помочь вам).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...