Frage

ich in das folgende Problem gestoßen: Ich schreibe ein Skript Linux-Bash, das macht folgendes:

  • Lesen Sie Zeile aus der Datei
  • abisolieren \n Zeichen aus dem Ende der Zeile liest gerade
  • Führen Sie den Befehl, der da drin ist

Beispiel: commands.txt

ls
ls -l
ls -ltra
ps as

Die Ausführung der bash-Datei sollte die erste Zeile erhalten, und führen Sie es aus, aber während der \n vorhanden, die Shell gibt nur „Befehl nicht gefunden: ls“ Dieser Teil des Skripts wie folgt aussieht

 read line

        if [ -n "$line" ]; then #if not empty line

                #myline=`echo -n $line | tr -d '\n'`
                #myline=`echo -e $line | sed ':start /^.*$/N;s/\n//g; t start'`

                myline=`echo -n $line | tr -d "\n"`
                $myline  #execute it

                cat $fname | tail -n+2 > $fname.txt
                mv $fname.txt $fname
        fi

kommentiert haben Sie die Dinge, die ich versuchte, bevor SO fragen. Jede Lösung? Ich bin mein Gehirn für die letzten paar Stunden über diese Zerschlagung ...

War es hilfreich?

Lösung

ich immer wie perl -ne 'chomp and print', für Zeilenumbrüche trimmen. Schön und leicht zu merken.

z. ls -l | perl -ne 'chomp and print'

Doch

Ich glaube nicht, dass Ihr Problem aber hier ist. Obwohl ich nicht sicher bin, verstehe ich, wie Sie die Befehle durch in Ihrem Shell-Skript zu dem ‚lesen‘ in der Datei vorbei sind.

Mit einem Testskript meiner eigenen wie diese (test.sh)

read line
if [ -n "$line" ]; then
  $line
fi

und eine Beispieleingabedatei wie folgt aus (test.cmds)

ls 
ls -l
ls -ltra

Wenn ich es wie dieses ./test.sh < test.cmds laufe, sehe ich das erwartete Ergebnis, das ist der erste Befehl ‚ls‘ auf dem aktuellen Arbeitsverzeichnis ausgeführt werden.

Vielleicht ist Ihre Eingabedatei enthält zusätzliche nicht druckbare Zeichen in das?

Mine wie folgt aussieht

od -c test.cmds 
0000000    l   s      \n   l   s       -   l  \n   l   s       -   l   t
0000020    r   a  \n                                                    
0000023

Von Ihrem Kommentar unten, ich vermute, Sie Wagenrücklauf haben können ( „\ r“) in der Eingabedatei, die nicht das gleiche wie eine neue Zeile ist. Ist die Eingabedatei ursprünglich im DOS-Format? Wenn ja, dann müssen Sie die 2-Byte-DOS Zeilenende „\ r \ n“, um die einzelnen Byte UNIX ein: „\ n“ konvertieren, die erwarteten Ergebnisse zu erzielen.

Sie sollten in der Lage sein, dies zu tun, indem Sie den „\ n“ für „\ r“ in einem Ihrer kommentiert aus Linien tauschen.

Andere Tipps

Jemand schrieb bereits ein Programm, das Shell-Befehle ausführt: sh-Datei

Wenn Sie wirklich wollen nur die erste Zeile einer Datei auszuführen: head -n 1 file |sh

Wenn Ihr Problem ist Carriage-Returns: tr -d '\r' <file |sh

Ich habe versucht, dies:

read line
echo -n $line | od -x

Für die Eingabe 'xxxx', erhalte ich:

0000000 7878 7878

Wie Sie sehen können, gibt es keine \n am Ende des Inhalts der Variablen. Ich schlage vor, das Skript mit der Option -x (bash -x script) laufen. Dadurch werden alle Befehle drucken, wie sie ausgeführt werden.

[EDIT] Ihr Problem ist, dass Sie commands.txt unter Windows bearbeitet. Nun enthält die Datei CRLF (0d0a) als Zeilentrennzeichen, die read verwirrt (und ls\r ist kein bekannter Befehl). Verwenden Sie dos2unix oder ähnlich in eine Unix-Datei zu machen.

Sie können auch versuchen, Wagenrücklauf mit Zeilenumbrüchen nur builtins mit Bash zu ersetzen:

line=$'a line\r' 
line="${line//$'\r'/$'\n'}" 
#line="${line/%$'\r'/$'\n'}"       # replace only at line end
printf "%s" "$line" | ruby -0777 -n -e 'p $_.to_s' 

Sie müssen eval Befehl


#!/bin/bash -x

while read  cmd
do
 if [ "$cmd" ]
 then
  eval "$cmd"
 fi
done

Ich lief es wie
./script.sh

Und datei.txt war:

ls
ls -l
ls -ltra
ps as

wenn auch nicht für ls arbeiten, empfehle ich einen Blick mit find 's -print0 Option

Das folgende Skript funktioniert (zumindest für mich):

#!/bin/bash

while read I ; do if [ "$I" ] ; then $I ; fi ; done ;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top