2013-04-19 5 views
-1

를 사용하여 CSV 파일의 열로 저장 I는 파일 내용이 처음에 공간으로 구분 기호를 가진 텍스트 파일이 있습니다. 그 모양은 다음과 같습니다.는 텍스트 파일의 각 라인을 읽고 펄

  • 첫 줄에는 처음부터 공백이 없습니다.
  • 두 번째 줄에는 2 개의 공백이 있습니다.
  • 세 번째 줄에는 처음에 4 칸이 있습니다.
  • 네 번째 줄에는 처음에 여백이 6 개 있습니다.

이 패턴은 텍스트 파일 (예 : 아래)과 같이 임의의 방식으로 파일 끝까지 반복됩니다.

  • 첫 번째 열에 공백이없는 :

    나는 텍스트 파일에서 이러한 라인을 읽고 패턴으로 라인을 저장할.

  • 두 번째 열에 2 개의 공백이 있습니다.
  • 세 번째 열에 4 칸.
  • CSV 파일의 네 번째 열에 여섯 개의 공백이 있습니다.

텍스트 파일 구조 (#으로 공간을 나타내는)된다

ABC 
##EFG"123" 
####<HIJK> 22: test file 
######LMNOP "Test" 
######sssstt"123" 
QRS 
##TU"223" 
####<www> 32: test2 file 
######yz test1 
####<www> 88: test3 file 
######rreeeww 
######oooiiiii 
##PP 
##ss 
####<qqq> 89: test6 file 
######hhhhggg 
######bbbbaaa 
######cccczzz 
######uu test3 

예상 출력 이미지 : output

내가 파일을 열고 읽는 방법을 알고, 펄에 새로운 오전 선을 통과하지만 CSV 열에 이러한 종류의 구조를 저장하는 방법을 이해하지 못합니다.

my $file = 'C:\\outputfile.txt'; 
open(my $fh, '<:encoding(UTF-8)', $file) or die "Could not open file '$file' $!"; 
while (my $row = <$fh>) { # reading each row till end of file 
    chomp $row; 
    //what should be done here ? 
} 

도와주세요. 그래, 내가 대답 할 수 있지만,이 좋은 또는 Perl 코드의 좋은 예되지 않습니다 : 당신이 코드에 대한 질문이있을 경우

+0

이미지를 제공하는 대신 예제 파일을 질문에 복사하십시오. 도움을 청하는 누군가 테스트를 위해 그것을 사용할 수 있습니다. –

+0

동일한 수의 공백으로 시작하는 줄이 여러 개인 경우 어떻게해야하는지 설명하지 않습니다. 게시 한 입력 내용에 필요한 출력을 표시하는 것이 좋습니다. – Borodin

+0

@ 보 로딘 흠, 질문을 읽어주세요. 저자는 그의 파일에서 더블 스페이스 - 구분자가 있다고 말했다. – gaussblurinc

답변

1

, 내가 말할 것이다. 쓰기가 빠릅니다.

my $previous_count = "-1"; #beginning, we will think, that no spaces. 
my $current_count = "0"; #current default value 
my $maximum_count = 3; #u say so 
my $to_written = ""; 
my $delimiter_between_columns = ","; 
my $newline_separator = ";"; 
my $symbol_at_the_beginning = "#"; #input any symbol. But I suppose, you want "\s" <- whitespace' symbol class. input it like this: $var = "\s"; 
my @aggregate_array_of_ports=(); 
while(my $row = <DATA>){ 
#ok, read.  
chomp($row);  
#print "row is : $row\n"; 
if($row =~ m/^([$symbol_at_the_beginning]*)/){ 
    #print length($1); 
    $current_count = length($1)/2; #take number of spaces divided by 2 
    $row =~ s/^[$symbol_at_the_beginning]+//; 
    #hint here, we can get counts as 0,1,2,3 <-see? 
    #if you take first and third word, you need to add 2 separators. 
    #OR if you take count with LESSER then previous count, it mean, that you need output  
    #print"prev : $previous_count and curr : $current_count\n "; 
    #print"I will write: $to_written\n"; 
    #print "\n PREV: $previous_count --> CURR: $current_count \n"; 
    if($previous_count>=$current_count){ 
     #output here 
     print "$to_written".$newline_separator."\n"; 
     $previous_count = 0; 
     $to_written = ""; 
    } 
    $previous_count = 0 if($previous_count==-1); 

    #print "$delimiter_between_columns x($current_count-$previous_count)\n"; 
    #print "current: $current_count previous: $previous_count \n"; 
    $to_written .= $delimiter_between_columns x ($current_count - $previous_count + (($current_count-$previous_count)==3?2:0))."$row"; 
    if ($current_count==($maximum_count-1)){ 
    #print "I input this!: $to_written\n"; 
    $to_written = prepare_to_input_four_spaces($to_written, $delimiter_between_columns);  
    } 
    $previous_count = $current_count; 
    #print"\n"; 
} 
} 
    #print "$to_written".$newline_separator."\n"; 
sub prepare_to_input_four_spaces{ 
    my $str = shift; #take string 
    my $delim = shift; 
    if ($str=~ m/(.+?[>])\s+(\d+)[:]\s+(.+?)$/){ 
    #here I want to find first capture group before [>] (also it includes) |(.+?[>])| 
    #next, some spaces |\s+| and I want to catch port |(\d+)|. 
    #next, |[:]| symbol and some spaces again |\s+| before the tail of the string. 
    #and will catch this tail: |(.+?)$|. 
    #where $ mean the right "border" of the string (really - end of the string) 
     $str = $1.$delim.$2.$delim.$3; 
     } 
     return $str; 
    } 

=pod 
__DATA__ 
ABC 
    EFG"123" 
    HIJK (12345) 
     LMNOP "Test" 
     sssstt"123" 
QRS 
    TU"223" 
    vwx"55" 
    www"88" 
     yz:test1 
__END__ 
=cut 
__DATA__ 
ABC 
##EFG"123" 
####<HIJK> 22: test file 
######LMNOP "Test" 
######sssstt"123" 
QRS 
##TU"223" 
####<www> 32: test2 file 
######yz test1 
####<www> 88: test3 file 
######rreeeww 
######oooiiiii 
##PP 
##ss 
####<qqq> 89: test6 file 
######hhhhggg 
######bbbbaaa 
######cccczzz 
######uu test3 
+0

안녕하세요. 이것은 정말로 도움이되었습니다. 고마워. –

+1

@KaushambiSuyal 안녕하세요! 내 대답이 정말로 도움이된다면, 내 대답에 대한 "수락/상향 회신"을 보게되어 기쁩니다.이것은 스택 오버플로에 대한 좋은 행동입니다. – gaussblurinc

+0

안녕하세요, 내 예상 출력에 약간의 업데이 트가 있습니다. 입력 및 출력 이미지에서 내 질문을 수정했습니다. 4 공백으로 시작하는 선에 대해 예상 출력에 표시된대로 세 개의 열로 더 분할해야합니다. 모든 것이 이전과 동일하게 유지됩니다. 내 코드를 귀하의 것과 매우 흡사하게 붙여 넣지는 않습니다. 그렇게 할 때 나를 도와 주실 분 있나요? –

0

아마이 당신을 위해 괜찮 : 난 그냥 헤더를 넣어 건너 뛰고로 구분 기호를 넣어했다 "|"우선은 그것을 바꿀 수있는 방법에 대해 설명합니다.

> perl -lne 'if(/^[^\#]/){if($.!=1){print "$a"};$a=$_;}else{s/^#*//g;$a.="|$_";}END{print $a}' temp 
ABC|EFG"123"|HIJK (12345)|LMNOP "Test"|sssstt"123" 
QRS|TU"223"|vwx"55"|www"88"|yz:test1 
+0

안녕하세요, 위 코드가 어떻게 작동하는지 자세히 설명해 주시겠습니까? 또한, 그것 # 실제로, 그 공간, 나는 해쉬로 표시했습니다. –

관련 문제