2010-06-10 20 views
8

मैं एक साधारण पर्ल स्क्रिप्ट लिखने की कोशिश कर रहा हूं जो * .csv को पढ़ता है, * .csv फ़ाइल की पंक्तियों को दो आयामी सरणी में रखता है, और तब सरणी से आइटम पर प्रिंट करता है और फिर सरणी की एक पंक्ति प्रिंट करता है ।पर्ल 2-आयामी सरणी कैसे मुद्रित करें?

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

open(CSV, $ARGV[0]) || die("Cannot open the $ARGV[0] file: $!"); 
my @row; 
my @table; 

while(<CSV>) { 
     @row = split(/\s*,\s*/, $_); 
     push(@table, @row); 
} 
close CSV || die $!; 

foreach my $element (@{ $table[0] }) { 
    print $element, "\n"; 
} 

print "$table[0][1]\n"; 

जब मैं इस स्क्रिप्ट मैं निम्न त्रुटि और कुछ भी नहीं प्रिंट प्राप्त चलाएँ: जबकि "सख्त refs" उपयोग में पर एक सरणी रेफरी के रूप में

स्ट्रिंग का उपयोग नहीं किया जा सकता ("1")। /scripts.pl लाइन 16.

मैंने कई अन्य मंचों में देखा है और अभी भी यह सुनिश्चित नहीं है कि इस समस्या को कैसे ठीक किया जाए। क्या कोई मुझे इस स्क्रिप्ट को ठीक करने में मदद कर सकता है?

+3

+1 को छोड़ते हुए से हर किसी का समय बर्बाद कर नहीं करने के लिए 'सख्त का उपयोग करें; चेतावनियों का प्रयोग करें; '। – Ether

+1

आपको वास्तव में 2 तर्क 'ओपन' से बचना चाहिए। इसमें कई समस्याएं हैं जो टालने के लिए सर्वोत्तम हैं (चर्चा के लिए इस 2001 के पोस्टमोनक्स पोस्ट देखें: http://www.perlmonks.org/?node_id=131085) इस एसओ पोस्ट को लेक्सिकल हैंडल पर जानकारी के लिए देखें: http: // stackoverflow .com/प्रश्न/613906/क्यों-करता-प्रोग्रामिंग-perl-use-local-not-my-for-filehandles – daotoad

+1

देखें ['perldoc perllol'] (http://perldoc.perl.org/perllol.html#Access -और-प्रिंटिंग) - एक्सेसिंग और प्रिंटिंग – Zaid

उत्तर

10

आप पर्ल-पार्लान्स में एक द्वि-आयामी सरणी (एओए या "ऐरे का ऐरे" नहीं बना रहे हैं)। यह पंक्ति:

push(@table, @row); 

@table करने के लिए @row में डेटा जोड़ देता है। का उपयोग करते समय split तुच्छ CSV फ़ाइलों के लिए ठीक है

my @table; 
while(<CSV>) { 
    my @row = split(/\s*,\s*/, $_); 
    push(@table, \@row); 
} 

, यह अपर्याप्त है: आप ताकि आप एक ही संदर्भ बार-बार धक्का नहीं है बजाय एक संदर्भ धक्का, और एक नया चर लूप के माध्यम से हर बार बनाने की जरूरत किसी और चीज़ के लिए। Text::CSV_XS बजाय की तरह एक मॉड्यूल का उपयोग करें:

use strict; 
use warnings; 
use Text::CSV_XS; 

my $csv = Text::CSV_XS->new() or die "Can't create CSV parser.\n"; 
my $file = shift @ARGV   or die "No input file.\n"; 
open my $fh, '<', $file  or die "Can't read file '$file' [$!]\n"; 

my @table; 
while (my $row = $csv->getline($fh)) { 
    push @table, $row; 
} 
close $fh; 

foreach my $row (@table) { 
    foreach my $element (@$row) { 
     print $element, "\n"; 
    } 
} 

print $table[0][1], "\n"; 
+0

ऐरे-ऑफ-सरणी सही नामकरण है। पर्ल में सूची-सूची के रूप में वास्तव में ऐसी कोई चीज़ नहीं है। ('Perllol' manpage के नाम के बावजूद। Sigh।) – friedo

+3

टेक्स्ट :: सीएसवी का उपयोग करने के लिए +1; यह वास्तव में मूर्ख नहीं है। –

+0

@friedo: प्वाइंट लिया गया। मैंने लोएल को कई बार इस्तेमाल किया है लेकिन गलत धारणाओं को फैलाने का कोई बहाना नहीं है। फिक्स्ड। –

3
my @arr = ([a, b, c], 
      [d, e, f], 
      [g, h, i], 
     ); 

for my $row (@arr) { 
    print join(",", @{$row}), "\n"; 
} 

प्रिंट

a,b,c 
d,e,f 
g,h,i 

संपादित करें: मैं दूसरों के गलत धक्का को पकड़ने के लिए क्रेडिट प्राप्त दूँगा।

2

आप 2 परिवर्तन की जरूरत है:

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

open(CSV, $ARGV[0]) || die("Cannot open the $ARGV[0] file: $!"); 
my @table; 

while(<CSV>) { 
    my @row = split(/\s*,\s*/, $_); 
    push(@table, \@row); 
} 
close CSV || die $!; 

foreach my $element (@{ $table[0] }) { 
    print $element, "\n"; 
} 

print "$table[0][1]\n";  
1
: पंक्ति के लिए

  1. उपयोग स्थानीय चर सरणी के लिए
  2. उपयोग संदर्भ आप में @table

तो अपने कार्यक्रम इस दिखना चाहिए डाल

शायद यह वही है जो आप वास्तव में चाहते हैं:

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

open(CSV, $ARGV[0]) || die("Cannot open the $ARGV[0] file: $!"); 
my @table; 

while(<CSV>) { 
     my @row = split(/\s*,\s*/, $_); 
     push(@table, \@row); 
} 
close CSV || die $!; 

foreach my $element (@{ $table[0] }) { 
    print $element, "\n"; 
} 

print "$table[0][1]\n"; 
+0

खुले आधुनिक प्रकार का उपयोग करना बेहतर होगा: ओपन (मेरा $ सीएसवी, '<', $ एआरजीवी [0]) –

0

बदलें

#push(@table, @row); 
push(@table, \@row); #push a reference to the array into each cell in @table. 

तो यह ठीक बाहर प्रिंट करता है।

+0

... लेकिन '@row की गलत चीज़ है 'लूप के अंदर नहीं बनाया गया है। –

+0

... लेकिन अगर आप '@ row' की एक प्रति के संदर्भ का उपयोग करने के लिए 'push @table, [@row]' कहें तो इसे ठीक किया जा सकता है। – mob

2

हैं जो आपको सूची तर्क के साथ धक्का कहते हैं, आप ढेर बुद्धिमान फैशन में शेष सूची (ओं) के साथ पहली सूची जोड़ देते हैं। Perldoc पर पुश के बारे में पढ़ें। तो push(@table, @row); का आपका कॉल अब @table सूची बना रहा है, न कि दो आयामी सरणी।

आपको कई पोस्ट प्राप्त हुई हैं जो @row के लिए एक संदर्भ संदर्भ को \@row पंक्तियों की एक सूची बनायेगी, और वास्तव में यह काम करती है। मैं इसे थोड़ा अलग करता हूं।बेशक, पर्ल के साथ, ऐसा करने का हमेशा एक और तरीका है!

संवैधानिक रूप से, आप बहु आयामी सूची बनाने के लिए किसी सूची के स्केलर तत्व में अज्ञात सरणी संदर्भ को भी दबा सकते हैं। पर्ल में संदर्भों के बारे में जानने के लिए सबसे महत्वपूर्ण बात यह है: 1) वे एक स्केलर हैं और 2) वे पर्ल - कोड, सरणी, हैश, किसी अन्य संदर्भ में कुछ भी संदर्भित कर सकते हैं। Perl Ref Tutorial के साथ कुछ समय बिताएं और यह और अधिक स्पष्ट हो जाएगा। अपने कोड के साथ, बस उस तत्व के आस-पास [ ] जोड़ें, जिसे आप अपनी सूची में दूसरा आयाम बनाना चाहते हैं, इसलिए push(@table, @row);push(@table, [ @row ]); होना चाहिए, उसी तरह, आप [ ] को अपने विभाजन के आस-पास डाल दें ताकि यह push(@table, [ split(/\s*,\s*/, $_) ]); हो जाए। यह एक साथ विभाजन और निर्माण करेगा परिणाम के लिए एक अज्ञात सरणी।

आपके पास जो विशिष्ट मुद्दा है, एक बहु आयामी सूची कैसे बनाएं और एक्सेस करें, टॉम क्रिस्टेंसेन के perllol tutorial में भी बहुत अच्छी तरह से इलाज किया जाता है आपके कोड के साथ आपके विशिष्ट मुद्दों के समाधान सीधे यहां निपटाए जाते हैं।

perllol में टॉम की उदाहरण से सटीक कोड के साथ अपने कोड नए सिरे से लिखना, यह इस हो जाता है:

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

my (@row, @table, $n, $rowref); 

while(<DATA>) { 
     chomp; 
     # regex to separate CSV (use of a cpan module for CSV STRONGLY advised... 
     @row = /(?:^|,)("(?:[^"]+|"")*"|[^,]*)/g; 
     for (@row) { 
      if (s/^"//) { s/"$//; s/""/"/g; } 
     } 
     push(@table, [ @row ]); #Note the [ ] around the list 
} 

# Now the table is created, print it: 
my $rowcnt=0; 
foreach $rowref (@table) { 
    print "row $rowcnt:\n"; 
    $rowcnt++; 
    print " [ @$rowref ], \n"; 
} 

# You can access the table in the classic [i][j] form: 
for my $i (0 .. $#table) { 
    $rowref = $table[$i]; 
    $n = @$rowref - 1; 
    for my $j (0 .. $n) { 
     print "element $i, $j of table is $table[$i][$j]\n"; 
    } 
} 

# You can format it: 
for my $i (0 .. $#table) { 
    print "$table[$i][0] $table[$i][1]\n"; 
    print "$table[$i][2]\n"; 
    print "$table[$i][3], $table[$i][4] $table[$i][5]\n\n"; 
} 


__DATA__ 
Mac,Doe,120 jefferson st.,Riverside, NJ, 08075 
Jack,McGinnis,220 hobo Av.,Phila, PA,09119 
"John ""Da Man""",Repici,120 Jefferson St.,Riverside, NJ,08075 
Stephen,Tyler,"7452 Terrace ""At the Plaza"" road",SomeTown,SD, 91234 
,Blankman,,SomeTown, SD, 00298 
"Joan ""Joan, the bone""",Jett,"9th, at Terrace plc",Desert City,CO,0
संबंधित मुद्दे