regex - डेटा को 3 सीमांकक के साथ विभाजित करें और इसे एक समय में 2 अलग सरणियों में संग्रहीत करें




perl split (2)

कई समस्याएं: खुली एक फ़ाइल नाम की आवश्यकता है, फाइलहेडल सामग्री नहीं (जब तक डेटा में फ़ाइल नाम नहीं है, जो इसे नहीं करता है)। सरणियों में मूल्यों को रखने के लिए, पुश का उपयोग करें, असाइनमेंट नहीं - आप एक ही समय में दो सरणियों को निर्दिष्ट नहीं कर सकते, वैसे भी, जैसा कि पहले से सब कुछ खाती है इसके अलावा, एक आदेश में सब कुछ करना संभव हो सकता है, लेकिन निश्चित रूप से पठनीय और रख-रखाव नहीं है।

#!/usr/bin/perl
use warnings;
use strict;

my $fh = *DATA{IO};
my (@A, @B);                                            # The comments just fix
                                                        # the stupid SO syntax highlighter.
my %result_hash = map { chomp; split /:/ } <$fh>;       #/
for my $key (sort { $a <=> $b } keys %result_hash) {
    my ($left, $right) = split /;/, $result_hash{$key}; #/
    push @A, split /,/, $left;                          #/
    push @B, split /,/, $right // q();
}

use Data::Dumper; print Dumper(\@A, \@B, \%result_hash);

__DATA__
1:X,Y,X,A,B;C,D,E,F
2:A,C,B,D
3:W,R,T,E;E

मेरे पास 3 सीमांकक के साथ डेटा है (:, और;) और डेटा में: और; केवल एक बार दिखाई देते हैं

__DATA__

1:X,Y,X,A,B;C,D,E,F 
2:A,C,B,D
3:W,R,T,E;E

चरण 1:

द्वारा विभाजित: और एक हैश का निर्माण

चरण 2:

जब तक हम पाते नहीं हैं, तब तक विभाजित करें और प्रत्येक कॉमा से अलग किए गए मान को सरणी में संग्रहीत करें;

चरण 3:

सब कुछ जो निम्नानुसार है; एक अन्य सरणी में होगा

उपरोक्त आंकड़ों से, मैं पहले सभी मूल्यों को स्टोर करने की कोशिश कर रहा हूं; सरणी में ए और सब कुछ सरणी में बी

Output
A = [X,Y,X,B,A,B,C,D,W,R,T,E]  B=[C,D,E,F,E]

नीचे कोड मैंने कोशिश की है

my (@A,@B);
sub Compare_results  
{
  my %result_hash = map { chomp; split ':', $_ } <DATA> ; #split by    colon and futher split by , and ; if any (doing it in insert_array)
 foreach my $key ( sort { $a <=> $b } (keys %result_hash) )
 {

   @A = split ",", (/([^;]+)/)[0], $result_hash{$key};
   @B = split ",", (/;([^;]+)/)[0], $result_hash{$key};
   print Dumper \@A,\@B;
 }    

}

लेकिन यह किसी भी परिणाम का उत्पादन नहीं कर रहा है, आउटपुट सरणियां खाली हैं, विभाजित डेटा का सही दृष्टिकोण क्या है, और; अलग-अलग सरणी में एक समय की दुकान पर एक शॉट पर तीन सीमांकक (एक हैश के निर्माण के लिए एक विभाजन) द्वारा एक अलग तरीके से विभाजित डेटा भी होता है

धन्यवाद


चाल प्रत्येक कदम अलग से करना है, और एक अलग क्रम में। क्रम को तबना देना है जब विश्लेषण करें । असल में, इसे टुकड़ों में तोड़ दो, फिर उन टुकड़ों के साथ कुछ करें

अगली चाल recursively टोकन है यह सब कुछ एक बार में टोकन करने की कोशिश करने के बजाय, छोटे टोकनों में छोटे टोकनों को तोड़ते हैं, और छोटे टॉकेन में होते हैं, और जब तक आप नीचे नहीं मारा पहली पंक्ति, फिर सीएसवी

इसे इस तरह देखकर, व्याकरण की पहली परत कुछ ऐसा दिखती है (सफेद स्थान पर ध्यान नहीं दिया जाता है)।

LINE = LINENUM : CSV ; CSV

ध्यान दें कि इस बिंदु पर हमें परवाह नहीं है कि सीएसवी में क्या है। हम मान लेंगे कि हमें अन्य बातों को उद्धृत करने और बचने से निपटने की ज़रूरत नहीं है।

इसके साथ निपटने के कुछ तरीके हैं एक को एक शॉट में पूरी बात को टोकाने के लिए एक regex का उपयोग करना है

my($linenum, @csvs) = $line =~ /^(.*?) : ([^;]*) ; (.*)$/x;

अब जब आपके पास @csvs को बाकी सब कुछ से अलग किया गया है, तो उन्हें @csvs होना चाहिए आप उन्हें अल्पसंख्यक पर विभाजित करके अधिक टोकन में बदल सकते हैं

push @$a, split /,/, $csvs[0];
push @$b, split /,/, $csvs[1];

और वहां तुम जाओ प्रत्येक परत को चुनकर आप एक बार में सब कुछ पार्स करने की कोशिश की जटिलता से बच सकते हैं।

आपके कार्य के रूप में, कई चीजें हैं जो इसे सुधारने के लिए किया जा सकता है। ज्यादातर इसे एक काम करते हैं , फ़ाइल को पार्स करते हैं। कुछ और फाइल खोलता है

इसके अलावा जिस चीज की जरूरत होती है उसे पारित किया जाना चाहिए और वापस लौटाया जाना चाहिए, कोई भी वैश्विक प्रयोग नहीं किया गया (हाँ, फ़ंक्शन के बाहर से my वैश्विक रूप से गिना जाता है)

use strict;
use warnings;
use v5.10;  # for say()

my($left, $right) = parse_whatever_this_format_is_called(*DATA);

say "Left:  ". join ", ", @$left;
say "Right: ". join ", ", @$right;

sub parse_whatever_this_format_is_called {
    # Take the filehandle to read as input
    my $fh = shift;

    # Declare our outputs
    my(@left, @right);

    # Parse each line
    while( my $line = <$fh>) {
        # Tokenize LINE = LINENUM : CSV ; CSV
        my($linenum, @csvs) = $line =~ /^(.*?) : ([^;]*) ; (.*)$/x;

        # Skip lines that didn't match
        next if !$linenum;

        # Split the CSVs
        push @left,  split /,/, $csvs[0];
        push @right, split /,/, $csvs[1];
    }

    # Return our outputs as references.
    # It's the only way to return multiple lists.
    # Also it avoids the expense of a copy.
    return( \@left, \@right );
}

__DATA__
1:X,Y,X,A,B;C,D,E,F
2:A,C,B,D
3:W,R,T,E;E




split