Platzhalter werden in der if-Anweisung nicht interpretiert

Platzhalter werden in der if-Anweisung nicht interpretiert

Ich schreibe gerade das folgende Skript. Der Code sucht in einem bestimmten Verzeichnis nach einem vom Benutzer eingegebenen Dateinamen. Das Skript prüft zunächst, ob die Eingabedatei eine GZIP-Datei ist. Wenn ja, führt es die entsprechenden Prüfungen durch. Wenn die Datei nicht GZIP-komprimiert ist, antwortet es mit einem inkompatiblen Dateitext.

Das Problem, auf das ich stoße, ist online 7. Unabhängig von der Dateierweiterung erhalte ich als endgültige Ausgabe eine inkompatible Datei.

#!/bin/bash
DATE=$(date +%Y-%m-%d)
L0_Report_Generator=("/home/ubuntu/$gzip_file")
echo -n "Enter File Directory:"$gzip_file 
read  $gzip_file
for gzip_file in {$L0_Report_Generator}; do
  if [[ $gzip_file = "test_sub"*"gz" ]] #Check file extension for gzip compression
      then
         gunzip $gzip_file
         echo "file Level 0 QC Check"
         echo ${DATE}
         echo "File Header"
         cat $gzip_file | head
         echo "Total Records"
         cat $gzip_file | wc -l
         echo "File Unique Records Size"
         cat $L0_Report_Generator | sort -u | wc -l
         rm $gzip_file 
    else [[ $gzip_file != "test_sub"*"gz" ]] #If file is anything other than .gz and csv - rort will not run
       then
         echo "incompatible file"
         fi
done

Antwort1

Wenn Sie mithilfe eines Platzhalterausdrucks innerhalb einer if-Anweisung nach der Dateinamenerweiterung „.gz“ suchen möchten, verwenden Sie einen Ausdruck wie den folgenden:

if [[ "${gzip_file}" = *.gz ]]; then echo true; else echo false; fi

So können Sie es testen:

if [[ "file.gz" = *.gz ]]; then echo true; else echo false; fi

Und:

if [[ "file.txt" = *.gz ]]; then echo true; else echo false; fi

Das erste Beispiel erzeugt trueals Ausgabe und das zweite Beispiel erzeugt false.

Schauen wir uns nun Ihren Code an. Ihre if-Anweisung enthält stattdessen den folgenden bedingten Ausdruck:

[[ $gzip_file = "test_sub"*"gz" ]]

Insbesondere schließen Sie „test_sub“ als Teilzeichenfolge in Ihr Übereinstimmungsmuster ein. Versuchen Sie, dies zu entfernen.

Antwort2

Zusätzlich zu dem, was @igal über die Überprüfung der Dateierweiterung gesagt hat: Sie haben viele Fehler in der Variablensyntax und -verwendung. Beginnen Sie mit Zeile 3:

L0_Report_Generator=("/home/ubuntu/$gzip_file")

Die Variable gzip_filewurde noch nicht gesetzt, daher $gzip_filewird sie durch nichts ersetzt, wenn die Shell sie erweitert. Außerdem weisen die Klammern var=(something)ein Array statt einer einfachen Variable zu, und in diesem Fall ergibt das keinen Sinn.

Die vierte Zeile, echo -n "Enter File Directory:"$gzip_file, hat dasselbe Problem mit der Variable gzip_file. Sie hat außerdem das Problem, dass sie echo -nunvorhersehbar ist und unter verschiedenen Versionen des Befehls unterschiedliche Ergebnisse liefert echo. Um einen String ohne Zeilenvorschub zu drucken, ist es viel besser, zu verwenden printf "%s" "string to print", aber in diesem Fall gibt es eine bessere Option, auf die ich gleich eingehen werde.

Die fünfte Zeile, read $gzip_file, scheint dazu gedacht zu sein, Benutzereingaben in die Variable einzulesen gzip_file, aber das tut sie nicht. In der Shell setzt man $vor einen Variablennamen, dassbekommtder aktuelle Wert der Variable. Hier möchten SieSatz$es, also müssen Sie das off: weglassen read gzip_file. Aber das würde ich nicht tun. Ich würde die Eingabeaufforderung (die Sie echoin Zeile 4 haben) als Teil des readBefehls einschließen:

read -p "Enter File Directory:" gzip_file

Ok, jetzt zu Zeile 6:

for gzip_file in {$L0_Report_Generator}; do

Dies scheint die Einstellunggzip_file wieder(ersetzt den Wert, den wir gerade readeingefügt haben). Versuchen Sie hier tatsächlich etwas festzulegen gzip_file, und die vorherigen Variablenreferenzen hätten wirklich eine andere Variable sein sollen (vielleicht gzip_dirstattdessen)?

Außerdem inergibt der Teil keinen Sinn. Ich glaube, Sie versuchen, die Variable zu verwenden L0_Report_Generator, aber in diesem Fall sollte die öffnende Klammernachdas Dollarzeichen. Aber das macht auch nicht ganz Sinn, denn ${L0_Report_Generator}es wird (wenn ich richtig verstehe, was das tun soll) nur der Pfad zu einem Verzeichnis sein. for ... initeriert nicht über den Inhalt von Verzeichnissen, sondern über eine Liste vonWörter, wie for var in word1 word2 "word 3 which has several spaces in it" word4; do. Wenn Sie eine Liste der Dateien in einem Verzeichnis erhalten möchten, müssen Sie ein Platzhalterzeichen verwenden, wie for var in dir/*; do-- die Shell erweitert das mit Platzhalterzeichen versehene Dateimuster in eine Liste übereinstimmender Dateien, wobei jede als Wort behandelt wird, und iteriert über sie. Sie haben auch die Möglichkeit, Übereinstimmungen auf Dateien mit einer bestimmten Erweiterung zu beschränken, indem Sie diese in das Muster aufnehmen, wie dir/*.gz.

Drei weitere Hinweise: Ich rate davon ab, Variablennamen in Großbuchstaben wie zu verwenden DATE, um Konflikte mit den verschiedenen Umgebungsvariablen in Großbuchstaben zu vermeiden, die für die Shell oder einige Dienstprogramme eine besondere Bedeutung haben. Setzen Sie Ihre Variablenreferenzen außerdem immer in doppelte Anführungszeichen (also „use“ "$var"statt nur „ $var), um unerwartete Anomalien bei der Analyse zu vermeiden. Und die elseKlausel hat keinen Test, also else [[ some test ]]ergibt „using“ keinen Sinn (und „ thenafter“ elseist ein Syntaxfehler).

Wenn ich also richtig verstanden habe, was das Skript tun soll, würde ich empfehlen, den Anfang des Skripts durch Folgendes zu ersetzen:

#!/bin/bash
date=$(date +%Y-%m-%d)    # Note lowercase variable
read -p "Enter File Directory:" gzip_dir
L0_Report_Generator="/home/ubuntu/$gzip_dir"

for gzip_file in "${L0_Report_Generator}"/*.gz; do

... Und dann (wenn Sie das obige .gz-Muster möchten) müssen Sie nicht ifprüfen, ob $gzip_filedie Erweiterung .gz vorliegt, da das Platzhaltermuster nur .gz-Dateien auflistet.

Noch eine Anmerkung:shellcheck.netist sehr hilfreich, um auf grundlegende Fehler in Shell-Skripten hinzuweisen. Vieles von dem, was ich aufgezeigt habe, fehlt, aber der Fehler then(den ich zunächst übersehen hatte) wurde erkannt.

verwandte Informationen