2012-06-17 6 views
6

मैं पर्ल के लिए अपेक्षाकृत नया हूं और मैं इस परियोजना में आया हूं कि मुझे थोड़ा कठिन समय है। प्रोजेक्ट का ऑब्जेक्ट दो सीएसवी फाइलों की तुलना करना है, जिनमें से एक में $ नाम, $ मॉडल, $ संस्करण और दूसरा होगा जिसमें $ name2, $ डिस्क, $ संग्रहण अंत में होगा परिणाम फ़ाइल में उस मिलान वाली रेखाएं होंगी और इस तरह की जानकारी को एक साथ रखेगी: $ नाम, $ मॉडल, $ संस्करण, $ डिस्क, $ संग्रहण।एक सरणी में एक रेखा को छोड़कर, पर्ल

मैंने ऐसा करने में कामयाब रहा है, लेकिन मेरी समस्या यह है कि जब प्रोग्राम गायब होने में तत्वों में से एक तोड़ता है। जब फ़ाइल में एक रेखा से गुज़रना पड़ता है तो वह उस रेखा पर रुक जाता है। मैं इस समस्या को कैसे ठीक करुं? कोई सुझाव या तरीका यह है कि मैं इसे कैसे उस रेखा को छोड़ सकता हूं और जारी रख सकता हूं?

यहाँ मेरी कोड है:

open(TESTING, '>testing.csv'); # Names will be printed to this during testing. only .net  ending names should appear 
open(MISSING, '>Missing.csv'); # Lines with missing name feilds will appear here. 

#open (FILE,'C:\Users\hp-laptop\Desktop\file.txt'); 
#my (@array) =<FILE>; 
my @hostname; #stores names 

#close FILE; 
#***** TESTING TO SEE IF ANY OF THE LISTED ITEMS BEGIN WITH A COMMA AND DO NOT HAVE A NAME. 
#***** THESE OBJECTS ARE PLACED INTO THE MISSING ARRAY AND THEN PRINTED OUT IN A SEPERATE 
#***** FILE. 
#open (FILE,'C:\Users\hp-laptop\Desktop\file.txt'); 
#test 
if (open(FILE, "file.txt")) { 

} 
else { 
    die " Cannot open file 1!\n:$!"; 

} 

$count = 0; 
$x  = 0; 
while (<FILE>) { 

    ($name, $model, $version) = split(","); #parsing 

    #print $name; 
    chomp($name, $model, $version); 

    if (($name =~ /^\s*$/) 
     && ($model =~ /^\s*$/) 
     && ($version =~ /^\s*$/)) #if all of the fields are blank (just a blank space) 
    { 

    #do nothing at all 
    } 
    elsif ($name =~ /^\s*$/) { #if name is a blank 
    $name =~ s/^\s*/missing/g; 
    print MISSING "$name,$model,$version\n"; 

    #$hostname[$count]=$name; 
    #$count++; 
    } 
    elsif ($model =~ /^\s*$/) { #if model is blank 
    $model =~ s/^\s*/missing/g; 
    print MISSING"$name,$model,$version\n"; 
    } 
    elsif ($version =~ /^\s*$/) { #if version is blank 
    $version =~ s/^\s*/missing/g; 
    print MISSING "$name,$model,$version\n"; 
    } 

    # Searches for .net to appear in field "$name" if match, it places it into hostname array. 
    if ($name =~ /.net/) { 

    $hostname[$count] = $name; 
    $count++; 
    } 

#searches for a comma in the name feild, puts that into an array and prints the line into the missing file. 
#probably won't have to use this, as I've found a better method to test all of the feilds ($name,$model,$version) 
#and put those into the missing file. Hopefully it works. 
#foreach $line (@array) 
#{ 
#if($line =~ /^\,+/) 
#{ 
#$line =~s/^\,*/missing,/g; 
#$missing[$x]=$line; 
#$x++; 
#} 
#} 

} 
close FILE; 

for my $hostname (@hostname) { 
    print TESTING $hostname . "\n"; 
} 

#for my $missing(@missing) 
#{ 
# print MISSING $missing; 
#} 
if (open(FILE2, "file2.txt")) { #Run this if the open succeeds 

    #open outfile and print starting header 
    open(RESULT, '>resultfile.csv'); 
    print RESULT ("name,Model,version,Disk, storage\n"); 
} 
else { 
    die " Cannot open file 2!\n:$!"; 
} 
$count = 0; 
while ($hostname[$count] ne "") { 
    while (<FILE>) { 
    ($name, $model, $version) = split(","); #parsing 

    #print $name,"\n"; 

    if ($name eq $hostname[$count]) # I think this is the problem area. 
    { 
     print $name, "\n", $hostname[$count], "\n"; 

     #print RESULT"$name,$model,$version,"; 
     #open (FILE2,'C:\Users\hp-laptop\Desktop\file2.txt'); 
     #test 
     if (open(FILE2, "file2.txt")) { 

     } 
     else { 
     die " Cannot open file 2!\n:$!"; 

     } 

     while (<FILE2>) { 
     chomp; 
     ($name2, $Dcount, $vname) = split(","); #parsing 

     if ($name eq $name2) { 
      chomp($version); 
      print RESULT"$name,$model,$version,$Dcount,$vname\n"; 

     } 

     } 

    } 

    $count++; 
    } 

    #open (FILE,'C:\Users\hp-laptop\Desktop\file.txt'); 
    #test 
    if (open(FILE, "file.txt")) { 

    } 
    else { 
    die " Cannot open file 1!\n:$!"; 

    } 

} 

close FILE; 
close RESULT; 
close FILE2; 
+2

अगली बार कृपया अपने कोड में सख्त उपयोग करें, यह आपको परेशान करने वाली बग के लिए सुरक्षा देता है। –

+0

कृपया 'सख्त उपयोग करें;', 'चेतावनियों का उपयोग करें;', अपने कोड को सही तरीके से इंडेंट करें, लेक्सिकल फाइलहैंडल्स के साथ खुले तर्क के संस्करण का उपयोग करें और सीखें कि सरणी फ़ंक्शंस ('पुश, मैप, grep') का उपयोग कैसे करें। – dgw

+1

आप जो भी सामग्री अपने आप को पर्ल को पढ़ाने के लिए उपयोग कर रहे हैं, मैं दृढ़ता से उन्हें छोड़ने की सलाह दूंगा - आपका कोड टेम्पलेट्स पर आधारित है जो कि बहुत ही पुरानी (वैश्विक नामित फ़ाइल हैंडल, खुले 2-Arg फॉर्म) से सीधे गलत है। कृपया इसे व्यक्तिगत रूप से न लें - यह स्पष्ट रूप से आपकी गलती नहीं है, लेकिन आप स्पष्ट रूप से उपयोग करने के मुकाबले बहुत बेहतर और अधिक आधुनिक किताबों/ट्यूटोरियल/कोड उदाहरणों से सीखकर बहुत अच्छी तरह से सेवा करेंगे। – DVK

उत्तर

2

मुझे लगता है कि आप next चाहते हैं, जिसे आप अपने वर्तमान यात्रा तुरंत समाप्त करने और अगले एक शुरू करने देता है:

while (<FILE>) { 
    ($name, $model, $version) = split(","); 
    next unless($name && $model && $version); 
    ...; 
    } 

हालत आप का उपयोग करें कि क्या पर निर्भर करता है मान आप स्वीकार करेंगे। मेरे उदाहरणों में, मैं मान रहा हूं कि सभी मूल्यों को सत्य होना चाहिए। वे सिर्फ रिक्त स्ट्रिंग नहीं होने की जरूरत है, तो हो सकता है आप के बजाय लंबाई की जांच:

while (<FILE>) { 
    ($name, $model, $version) = split(","); 
    next unless(length($name) && length($model) && length($version)); 
    ...; 
    } 

क्या आप जानते हैं प्रत्येक क्षेत्र को मान्य करने के लिए कैसे हैं, तो आप उन लोगों के लिए सबरूटीन्स हो सकता है:

while (<FILE>) { 
    ($name, $model, $version) = split(","); 
    next unless(length($name) && is_valid_model($model) && length($version)); 
    ...; 
    } 

sub is_valid_model { ... } 

अब आप बस यह तय करने की ज़रूरत है कि आप इसे पहले से क्या कर रहे हैं में एकीकृत करना है।

+0

आपके इनपुट के लिए बहुत बहुत धन्यवाद। मैं इसके साथ अपने कोड को फिर से बनाने की कोशिश करूंगा और क्या होता है पोस्ट करें! – user1462038

2

आपको अपने प्रोग्राम के शीर्ष पर use strict और use warnings जोड़कर शुरू करना चाहिए, और पहले उपयोग के बिंदु पर my के साथ सभी चर घोषित करना चाहिए। इससे कई सरल गलतियों को प्रकट किया जाएगा जो अन्यथा स्पॉट करना मुश्किल है।

तुम भी open और शाब्दिक filehandles के लिए तीन पैरामीटर का उपयोग करना चाहिए, और फ़ाइलों को खोलने पर अपवाद की जाँच के लिए पर्ल मुहावरा एक open कॉल करने के लिए or die जोड़ना है। if सफलता पथ अपशिष्ट स्थान के लिए एक खाली ब्लॉक के साथ बयान और अपठनीय बन गया। एक open कॉल इस

open my $fh, '>', 'myfile' or die "Unable to open file: $!"; 

की तरह दिखना चाहिए अंत में, यह जब आप CSV फ़ाइलों संभाल रहे हैं वहाँ के रूप में एक सरल split /,/ का उपयोग करने में नुकसान का एक बहुत कुछ कर रहे हैं एक पर्ल मॉड्यूल का उपयोग करने के ज्यादा सुरक्षित है। Text::CSV मॉड्यूल ने आपके लिए सभी काम किए हैं और सीपीएएन पर उपलब्ध हैं।

आप समस्या यह है कि, पहली फ़ाइल के अंत में पढ़ने के बाद, आप दूसरे नेस्टेड लूप में एक ही हैंडल से पढ़ने से पहले इसे रिवाइंड या फिर से खोलें नहीं। इसका मतलब है कि उस फ़ाइल से कोई और डेटा नहीं पढ़ा जाएगा और कार्यक्रम व्यवहार करेगा जैसे कि यह खाली है।

यह एक ही फाइल को पढ़ने के लिए सैकड़ों बार पढ़ने के लिए एक बुरी रणनीति है। अगर फ़ाइल उचित आकार का है तो आपको जानकारी रखने के लिए स्मृति में डेटा संरचना बनाना चाहिए। एक पर्ल हैश आदर्श है क्योंकि यह आपको किसी दिए गए नाम से संबंधित डेटा को तुरंत देखने की अनुमति देता है।

मैंने आपके कोड का एक संशोधन लिखा है जो इन बिंदुओं को प्रदर्शित करता है। कोड के परीक्षण के लिए यह अजीब होगा क्योंकि मेरे पास कोई नमूना डेटा नहीं है, लेकिन यदि आपको समस्याएं जारी रहती हैं तो कृपया हमें बताएं।

use strict; 
use warnings; 

use Text::CSV; 

my $csv = Text::CSV->new; 

my %data; 

# Read the name, model and version from the first file. Write any records 
# that don't have the full three fields to the "MISSING" file 
# 
open my $f1, '<', 'file.txt' or die qq(Cannot open file 1: $!); 

open my $missing, '>', 'Missing.csv' 
    or die qq(Unable to open "MISSING" file for output: $!); 
    # Lines with missing name fields will appear here. 

while (my $line = csv->getline($f1)) { 

    my $name = $line->[0]; 

    if (grep $_, @$line < 3) { 
    $csv->print($missing, $line); 
    } 
    else { 
    $data{$name} = $line if $name =~ /\.net$/i; 
    } 
} 

close $missing; 

# Put a list of .net names found into the testing file 
# 
open my $testing, '>', 'testing.csv' 
    or die qq(Unable to open "TESTING" file for output: $!); 
    # Names will be printed to this during testing. Only ".net" ending names should appear 

print $testing "$_\n" for sort keys %data; 

close $testing; 

# Read the name, disk and storage from the second file and check that the line 
# contains all three fields. Remove the name field from the start and append 
# to the data record with the matching name if it exists. 
# 
open my $f2, '<', 'file2.txt' or die qq(Cannot open file 2: $!); 

while (my $line = $csv->getline($f2)) { 

    next unless grep $_, @$line >= 3; 

    my $name = shift @$line; 
    next unless $name =~ /\.net$/i; 

    my $record = $data{$name}; 
    push @$record, @$line if $record; 
} 

# Print the completed hash. Send each record to the result output if it 
# has the required five fields 
# 
open my $result, '>', 'resultfile.csv' or die qq(Cannot open results file: $!); 

$csv->print($result, qw(name Model version Disk storage)); 

for my $name (sort keys %data) { 

    my $line = $data{$name}; 

    if (grep $_, @$line >= 5) { 
    $csv->print($result, $data{$name}); 
    } 
} 
+0

इसके लिए आपको बहुत बहुत धन्यवाद! इस कोड को देखने से मुझे बेहतर समझ मिल रही है कि मुझे इसके बारे में कैसे जाना चाहिए। एकमात्र समस्या यह है कि मुझे सीपीएएन मॉड्यूल का उपयोग करने की अनुमति नहीं है। – user1462038

+0

यदि आपको "अनुमति नहीं है", तो यह सुझाव देता है कि यह होमवर्क है और न केवल एक समस्या है जिसे आप "पार कर चुके हैं"। पूर्ण प्रकटीकरण सिर्फ विनम्र है। – mlp

+0

मुझे खेद है, नहीं। यह होमवर्क नहीं है। मुझे बस उपयोग किए जाने वाले कंप्यूटर पर प्रोग्राम को संशोधित करने की अनुमति नहीं है। वैसे भी आपके विचार के लिए धन्यवाद। – user1462038

संबंधित मुद्दे