2013-10-08 4 views
0

Это мой табуляцией входной файлPerl неправильно добавляет символы новой строки?

Name<tab>Street<tab>Address 

Это, как я хочу, чтобы мой выходной файл, чтобы выглядеть как

Street<tab>Address<tab>Address 

(да дублировать следующие две колонки) Мой выходной файл выглядит следующим образом вместо

Street<tab>Address 
     <tab>Address 

Что происходит с perl? Это мой код.

open (IN, $ARGV[0]); 

open (OUT, ">output.txt"); 
while ($line = <IN>){ 

    chomp $line; 
    @line=split/\t/,$line; 

    $line[2]=~s/\n//g; 
    print OUT $line[1]."\t".$line[2]."\t".$line[2]."\n"; 
} 

close(OUT); 
+3

Я думаю, что вы, возможно, файл DOS работает на UNIX. попробуйте dos2unix на ваш входной файл – KeepCalmAndCarryOn

+1

Боковой комментарий. Я бы избегал переменных '$ line' и' @ line', может быть, '@ lineparts' – justintime

+1

' use Data :: Dumper; Хранитель $ Data :: :: Useqq = 1; print Dumper $ line; ' – TLP

ответ

0

Вы пытались устранить не только «\ n», но и «\ r» ???

$file[2] =~ s/\r\n//g; 
$file[3] =~ s/\r\n//g; # Is it the "good" one? 

Это может сработать. Окончания строк DOS также могут быть «\ r» (не только «\ n»).

+0

Обычно я пишу' s/[\ r \ n] + $ // 'или' s/[\ s \ r \ n] + $ // ', чтобы убрать конец строк, чтобы приспособить любой стиль окончания строки. – AdrianHHH

+2

'[\ s \ r \ n]' может быть более сжато записано '\ s', так как оба' \ r' и '\ n' являются простыми символами. – TLP

4

Прежде всего, вы должны всегда

  • use strict и use warnings для даже самых тривиальных программ. Вы также должны объявить каждый из ваших переменных, используя my как можно ближе к их первого использования

  • использовать лексические дескрипторов файлов и форму трехпараметрическую open

  • проверки успех каждыйopen вызов, и die строкой, которая включает в себя $!, чтобы показать причину отказа

Отметим также, что нет никакой необходимости в явном виде открытой фил es, которые указаны в командной строке, которые отображаются в @ARGV: вы можете просто прочитать их, используя <>.

Как уже было сказано, похоже, что вы читаете файл DOS или Windows происхождения в системе Linux. Вместо того, чтобы использовать chomp, вы можете удалить все завершающие пробельные символы из каждой строки, используя s/\s+\z//. Поскольку CR и LF считаются «пробелами», это приведет к удалению всех терминаторов строк из каждой записи. Помните, однако, что если конечное пространство имеет значение или последнее поле может быть пустым, это также удалит пробелы и вкладки. В этом случае более подходящим является s/[\r\n]+\z//.

Эта версия программы отлично работает.

use strict; 
use warnings; 

@ARGV = 'addr.txt'; 

open my $out, '>', 'output.txt' or die $!; 

while (<>) { 
    s/\s+\z//; 
    my @fields = split /\t/; 
    print $out join("\t", @fields[1, 2, 2]), "\n"; 
} 

close $out or die $!; 
2

Если вы знаете заранее происхождения файла данных, и знаете, что это DOS-подобный файл, который завершает запись с CR LF, вы можете использовать PerlIOcrlf слой при открытии файла. Как это

open my $in, '<:crlf', $ARGV[0] or die $!; 

, то все записи будут появляться до конца всего "\n", когда они считываются в системе Linux.

Общее решение этой проблемы - установить PerlIO::eol. Тогда вы можете написать

open my $in, '<:raw:eol(LF)', $ARGV[0] or die $!; 

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

0

Другой способ избежать конца проблемы на линии, чтобы улавливать только символы, которые вы заинтересованы в:

open (IN, $ARGV[0]); 

open (OUT, ">output.txt"); 
while (<IN>) { 
    print OUT "$1\t$2\t$2\n" if /^(\w+)\t\w+\t(\w+)\s*/; 
} 

close(OUT); 
Смежные вопросы