2008-10-02 15 views
5

यहां काम पर हम एक न्यूजलेटर सिस्टम पर काम कर रहे हैं जो हमारे ग्राहक उपयोग कर सकते हैं। एक इंटर्न के रूप में मेरी नौकरियों में से एक पहेली के छोटे टुकड़ों के साथ मदद करने के लिए है। इस मामले में मुझे जो करना है, वह ईमेल सर्वर के लॉग को संदेशों को बाउंस करने के लिए स्कैन करता है और ईमेल जोड़ता है और ईमेल को "खराब ईमेल डेटाबेस" पर बाउंस करने का कारण होता है।मैं एक सूची में एक पाइप से अलग स्ट्रिंग कैसे विभाजित कर सकता हूं?

बुरा ईमेल तालिका में दो कॉलम होते हैं: 'ईमेल' और 'कारण' मैं निम्नलिखित कथन का उपयोग लॉग से जानकारी मिलती है और पर्ल स्क्रिप्ट

grep " 550 " /var/log/exim/main.log | awk '{print $5 "|" $23 " " $24 " " $25 " " $26 " " $27 " " $28 " " $29 " " $30 " " $31 " " $32 " " $33}' | perl /devl/bademails/getbademails.pl 

आप sugestions है, तो को भेजने के लिए एक अधिक कुशल अजीब लिपि पर, तो मुझे उनको भी सुनकर खुशी होगी लेकिन मेरा मुख्य फोकस पर्ल स्क्रिप्ट है। पर्ल स्क्रिप्ट के लिए अजीब पाइप "बाउंस के लिए [email protected]|reason"। मैं इन तारों में लेना चाहता हूं, उन्हें विभाजित करें और दो अलग-अलग हिस्सों को डेटाबेस में अपने संबंधित कॉलम में डाल दें। यहां मेरे पास है:

#!usr/bin/perl                                            

use strict; 
use warnings; 
use DBI; 

my $dbpath = "dbi:mysql:database=system;host=localhost:3306"; 
my $dbh = DBI->connect($dbpath, "root", "******") 
    or die "Can't open database: $DBI::errstr"; 

while(<STDIN>) { 
    my $line = $_;          
    my @list = # ? this is where i am confused 
    for (my($i) = 0; $i < 1; $i++) 
    { 
     if (defined($list[$i])) 
     { 
      my @val = split('|', $list[$i]); 
      print "Email: $val[0]\n"; 
      print "Reason: $val[1]"; 
      my $sth = $dbh->prepare(qq{INSERT INTO bademails VALUES('$val[0]', '$val[1]')}); 
      $sth->execute();                         
      $sth->finish();                                            
     } 
    } 
} 
exit 0; 
+0

आपको उन सभी grep और awk की आवश्यकता नहीं है। यदि आप /var/log/exim/main.log की सामग्री का केवल एक उदाहरण प्रदान कर सकते हैं तो हम आपको एक पर्ल स्क्रिप्ट बनाने में बेहतर मदद कर सकते हैं, जो सब कुछ grep और awk करता था। – bmdhacks

+0

मुझे लगता है कि पर्ल में पूरी चीज को कोड करना बेहतर होगा। पर्ल से प्रत्येक पंक्ति के लिए कोड को दोबारा बनाने के लिए आपको शायद स्पीड बूस्ट दिखाई देगा। –

उत्तर

13

कुछ इस तरह काम करेंगे:

while(<STDIN>) { 
    my $line = $_; 
    chomp($line); 
    my ($email,$reason) = split(/\|/, $line); 
    print "Email: $email\n"; 
    print "Reason: $reason"; 
    my $sth = $dbh->prepare(qq{INSERT INTO bademails VALUES(?, ?)}); 
    $sth->execute($email, $reason);                         
    $sth->finish();                                            
} 

आप यह आसान सिर्फ पर्ल में पूरी बात करने के लिए मिल सकती है। "अगली जब तक/550 /" grep को प्रतिस्थापित नहीं कर सकता है और एक regex शायद अजीब को प्रतिस्थापित कर सकता है।

+0

उसने ऐसा किया। संक्षिप्त उत्तर: पाइप से बचने में एक रेगेक्स का उपयोग करें, उद्धरणों में भागने से यह काम नहीं करेगा, इस तरह विभाजित (/ \ | /, $ string); – HoldOffHunger

7

मुझे यकीन नहीं है कि आप @list में क्या रखना चाहते हैं? यदि अजीब पाइप एक प्रविष्टि प्रति पंक्ति है, तो आपके पास $ लाइन में होगा, और आपको @list पर लूप की आवश्यकता नहीं है।

उसने कहा, यदि आप इसे पर्ल में पाइप करने जा रहे हैं, तो पहली जगह grep और AWK से परेशान क्यों हो? DBI के बारे में

#!/ust/bin/perl -w 
use strict; 

while (<>) { 
    next unless/550 /; 
    my @tokens = split ' ', $_; 
    my $addr = $tokens[4]; 
    my $reason = join " ", @tokens[5..$#tokens]; 

    # ... DBI code 
} 

साइड नोट कहता है: तुम सच में प्लेसहोल्डर का उपयोग करना चाहिए, ताकि एक "बुरा ईमेल" अपने डेटाबेस में एसक्यूएल इंजेक्षन करने में सक्षम नहीं होगा।

+0

+1 ... महान दिमाग एक जैसे zigdon सोचते हैं ;-) – toolkit

+1

इसे सरल बनाने के तरीके के रूप में विभाजित करने के लिए तीसरे तर्क को देखें। – dland

5

क्यों grep और awk से गुजरना और सीधे पर्ल जाना है?

अस्वीकरण: मैं अगर निम्न कोड को संकलित की जाँच नहीं की है:

while (<STDIN>) { 
    next unless /550/; # skips over the rest of the while loop 
    my @fields = split; 
    my $email = $fields[4]; 
    my $reason = join(' ', @fields[22..32]); 
    ... 
} 

संपादित करें: एक और अनुकूलन :-)

आशा इस में मदद करता है के लिए @dland's comment देखते हैं?

+0

22 वें स्थान के बाद विभाजन को रोकने के लिए आप विभाजित (/ /, $ _, 22) विभाजित कर सकते हैं। इससे @fields को बाद में टुकड़ा करने से बचा जाता है। – dland

3
my(@list) = split /\|/, $line; 

यदि आपके पास लाइन की पूंछ में अतिरिक्त पाइप प्रतीक हैं तो यह @list में दो से अधिक प्रविष्टियां उत्पन्न करेगा। इससे बचने के लिए, उपयोग करें:

$line =~ m/^([^|]+)\|(.*)$/; 
my(@list) = ($1, $2); 

रेगेक्स में डॉलर तर्कसंगत रूप से अनिवार्य है, लेकिन दस्तावेज़ 'लाइन का अंत' भी है।

+0

मैं दो स्ट्रिंग्स में विभाजित करने के लिए "my @list = split/\ | /, $ line, 2" का उपयोग करने के बजाय सुझाव देना चाहता हूं। – tsee

+1

जब तक आप मैच की सफलता की जांच नहीं कर लेते तब तक $ 1 का कभी भी उपयोग न करें! यदि मैच विफल रहता है, तो आपको $ 1 का स्टेल मिलता है। बुरा विचार। –

5

क्या आपने इसके बजाय App::Ack का उपयोग करने पर विचार किया है? किसी बाहरी प्रोग्राम को खोलने के बजाय, आप इसके बजाय पर्ल का उपयोग कर सकते हैं। दुर्भाग्यवश, आपको ack प्रोग्राम कोड के माध्यम से वास्तव में यह समझने के लिए पढ़ना होगा कि आपको यह कैसे करना है, लेकिन आपको परिणामस्वरूप एक और पोर्टेबल प्रोग्राम प्राप्त करना चाहिए।

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

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