2016-03-25 5 views
1

dieses Programm Gemeint ist damit zu tun, dass es eine Textdatei liest, die wie folgt aussieht:Perl einfacher Filehandling von Text

Artikel \ t \ t Preis

Apfel \ t \ t 20

Orange \ t \ t 50

Kalk \ t \ t 30

I Split-Funktion bin mit diesen zwei Spalten aufgeteilt und dann sollte ich einen 25% Rabatt auf alle Artikel gelten und ausdrucken zu einem neue Datei. Mein Code macht bisher, was ich will, aber die neue Textdatei hat einen '0' Wert unter meiner letzten Nummer in der Preisspalte. Ich habe auch zwei Fehler, wenn ich es mit „Verwendung Warnungen“ laufen, die sind:

Verwendung von nicht initialisierten Wert $ item in Multiplikation * ...

Verwendung von nicht initialisierten Wert $ item [0] in Verkettung (.) ...

ich sollte auch Gesamtzahl der Elemente berechnet sagen, aber ich mag 5 1en erhalten anstelle von 5. (11111 statt 5)

use strict; 
use warnings; 

my $filename = 'shop.txt'; 
if (-e $filename){ 
    open (IN, $filename); 
} 
else{ 
    die "Can't open input file for reading: $!"; 
} 
open (OUT,">","discount.txt") or die "Can't open output file for writing: $!"; 

my $header = <IN>; 

print OUT $header; 

while (<IN>) { 
    chomp; 
    my @items = split(/\t\t/); 
    foreach my $item ($items[1]){ 
     my $discount = $item * (0.75); 
     print OUT "$items[0]\t\t$discount\n"; 
    } 
} 
+0

Das Skript sollte funktionieren, wenn keine leeren Zeilen vorhanden sind und alle Elemente durch zwei Registerkarten getrennt sind. Die Warnungen, die Sie erhalten, weisen darauf hin, dass dies nicht der Fall ist. –

Antwort

2

Das ist zu kompliziert und nicht klar, was sind Sie tue in foreach loop und du überspringst keine leeren Zeilen. Halten Sie es einfach:

use warnings; 
use strict; 
use v5.10; 

<>; # skip header 
while(my $line = <>) 
{ 
    chomp $line; 
    next unless ($line); 

    my ($title, $price) = split /\s+/, $line; 
    if($title && defined $price) 
    { 
     $price *= 0.75; 
     say "$title\t\t$price"; 
    } 
} 

und laufen wie

perl script.pl <input.txt >output.txt 
+0

Vielen Dank für Ihre Antwort. Was soll ich tun, wenn ich die Gesamtzahl der Artikel berechnen möchte, aber nur 11111 anstelle von 5? – BSileNTz

+0

Nicht sicher, ich verstehe, was Sie wollen. Machen Sie Zähler und erhöhen Sie ihn bei jedem gültigen Eintrag. –

0

ich diesen Ansatz verwenden würde

#!/usr/bin/perl 

use strict; 
use warnings; 

my %items; 
my $filename = 'shop.txt'; 
my $discount = 'discount.txt'; 

open my $in, '<', $filename or die "Failed to open file! : $!\n"; 
open my $out, ">", $discount or die "Can't open output file for writing: $!"; 

print $out "Item\t\tPrice\n"; 
my $cnt = 0; 
while (my $line = <$in>) { 
    chomp $line; 
    if (my ($item,$price) = $line =~ /(\w.+)\s+([0-9.]+)/){ 
     $price = $price * (0.75); 
     print $out "$item\t\t$price\n"; 
     $items{$item} = $price; 
     $cnt++; 
    } 
} 
close($in); 
close($out); 

my $total = keys %items; 

print "Total items - $total \n"; 
print "Total items - $cnt\n"; 

regex Einfanggruppen Mit dem Artikel- und Preis aufzeichnen zu können (mit \ w +. Wenn der Artikel 2 Wörter wie Apfelmus enthält, verhindert dies auch, dass leere Zeilen in die Datei gedruckt werden.

Ich habe auch den Artikel und Preis Header hart codiert, wahrscheinlich eine gute Idee, wenn Sie eine konsistente Kopfzeile verwenden werden.

Hoffe, es hilft

--- aktualisieren ----

Ich habe 2 Beispiele für eine Gesamtzählung in meinem Skript. Die erste verwendet einen Hash und druckt die Hash-Größe aus, die zweite Methode verwendet einen Zähler. Die Hash-Option ist gut, es sei denn, Ihre Liste enthält zwei identische Elemente. In diesem Fall wird der Schlüssel des Hashs mit dem letzten gefundenen Element überschrieben, das denselben Namen hat. Der Zähler ist eine einfache Lösung.

+0

Vielen Dank für Ihre Antwort, aber um ehrlich zu sein, ich versuche, Regex so viel wie möglich zu vermeiden, weil ich es so verwirrend finde, aber es kann auch sein, weil ich kürzlich angefangen habe. – BSileNTz

+0

Ich kenne das Gefühl, Als ich anfing, Perl zu benutzen, tat ich dasselbe, aber seither finde ich, dass Regex Super Power und sehr nützlich ist und ich benutze es die ganze Zeit. In Ihrem Beispiel bevorzuge ich die Verwendung von Regex, falls sich Ihre Shop-Datei ändert oder eine andere 4 Leerzeichen verwendet, anstatt einen Tab zu verwenden (was bei Split ('\ t \ t') ignoriert würde, aber in jedem Fall sieht es so aus Sie haben genug Hilfe in diesem Thread bekommen, um Sie in Gang zu bringen. –

+0

Ja danke nochmal, wissen Sie, wie ich die Gesamtzahl der Artikel aus meinen .txt-Dateien ausdrucken kann? Sagen wir, ich habe 10 Artikel mit Preisen in der Textdatei Ich möchte 10 ausgedruckt werden, aber ich weiß nicht, wie – BSileNTz

1
use strict; 
use warnings; 

my $filename = 'shop.txt'; 
if (-e $filename){ 
    open (IN, $filename); 
} 
else{ 
    die "Can't open input file for reading: $!"; 
} 
open (OUT,">","discount.txt") or die "Can't open output file for writing: $!"; 

my $header = <IN>; 
my $item; 
my $price; 

print OUT $header; 

while (<IN>) { 
    chomp; 
    ($item, $price) = split(/\t\t/); 

    my $discount = $price*0.75; 
    print OUT "$item $discount\n"; 

} 

Dies sollte helfen!:)

+0

Einige Erklärungen, was Sie getan haben, wäre hilfreich.Antworten, die nur Code-Dumps sind und "versuchen Sie es" oder "hoffe, dass dies hilft" sind weniger nützlich. –

+0

Ja sicher ! :) Statt es in einem Array (@items) zu speichern, gibt es eine Möglichkeit, die Artikel- und Preisvariablen separat zu speichern, wie in der Abbildung gezeigt: ($ item, $ price) = split (/ \ t \ t /); Das Argument in Split ist das Trennzeichen, durch das die Strings getrennt werden. In diesem Fall ist es eine doppelte Registerkarte. daher \ t \ t. Dann kann die Operation, die Sie durchführen müssen, leicht auf den Preis bezogen werden. – Mounika

1

Wenn die Gesamtelementanzahl Ihnen nicht sehr wichtig ist:

$ perl -wane '$F[1] *= 0.75 if $. > 1; print join("\t", @F), "\n";' input.txt 

Ausgang:

Item Price 
apple 15 
orange 37.5 
lime 22.5 

Wenn Sie wirklich den gesamten Artikel benötigen zählen:

$ perl -we 'while (<>) { @F = split; if ($. > 1) { $F[1] *= 0.75; $i++ } print join("\t", @F), "\n"; } print "$i items\n";' input.txt 

Ausgabe:

Item Price 
apple 15 
orange 37.5 
lime 22.5 
3 items