Wie kann ein Perl-Skript (idiomatisch) am besten fehlgeschlagen (mit -n / -p ausgeführt) werden, wenn die Eingabedatei nicht gefunden wird?

11
$ perl -pe 1 foo && echo ok
Can't open foo: No such file or directory.
ok

Ich möchte wirklich, dass das Perl-Skript fehlschlägt, wenn die Datei nicht vorhanden ist. Was ist der "richtige" Weg, um -p oder -n zum Fehlschlagen zu bringen, wenn die Eingabedatei nicht vorhanden ist?

William Pursell
quelle

Antworten:

6

Der Schalter -p ist nur eine Verknüpfung zum Umschließen Ihres Codes (das Argument nach -e) in diese Schleife:

LINE:
  while (<>) {
      ...             # your program goes here
  } continue {
      print or die "-p destination: $!\n";
  }

(-n ist das gleiche, jedoch ohne den Continue-Block.)

Der <>leere Operator entspricht readline *ARGV, und das öffnet jedes Argument nacheinander als Datei zum Lesen. Es gibt keine Möglichkeit, die Fehlerbehandlung dieses impliziten Öffnens zu beeinflussen, aber Sie können die Warnung, die es ausgibt, schwerwiegend machen (beachten Sie, dass dies auch mehrere Warnungen betrifft, die sich auf den Schalter -i beziehen):

perl -Mwarnings=FATAL,inplace -pe 1 foo && echo ok
Grinnz
quelle
@MarkReed inplace ist die Warnungskategorie, an der wir interessiert sind. Es gibt keinen Grund, andere Warnungen zu beeinflussen.
Grinnz
Aus Warnungen :The presence of the word "FATAL" in the category list will escalate warnings in those categories into fatal errors in that lexical scope.
Grinnz
Richtig, inplaceist die Kategorie; ohne es -Mwarnings=FATALbedeutet FATAL => all, was wir nicht wollen. verstanden.
Mark Reed
4

Setzen Sie ein Flag im Hauptteil der Schleife und überprüfen Sie das Flag im END-Block am Ende des Oneliner.

perl -pe '$found = 1; ... ;END {die "No file found" unless $found}' -- file1 file2

Beachten Sie, dass dies nur fehlschlägt, wenn keine Datei verarbeitet wurde.

Um das Problem zu melden, wenn nicht alle Dateien gefunden wurden, können Sie Folgendes verwenden

perl -pe 'BEGIN{ $files = @ARGV} $found++ if eof; ... ;END {die "Some files not found" unless $files == $found}'
Choroba
quelle
1
Wenn Ihr Skript Dateien als Argumente verwenden soll, anstatt sie von stdin zu lesen, wäre eine leichtere Alternative zu dieser Lösung BEGIN{die "File not found" unless -f $ARGV[0]}. (Ich sage leichter, weil es nicht darum geht, eine Flagge zu setzen und 2 Codes hinzuzufügen)
Dada
Es wird auch davon ausgegangen, dass alle Dateien eine Länge ungleich Null haben.
Tanktalus