Jede Zeile in einer bestimmten Datei ' a.txt ' enthält das Verzeichnis / den Pfad zu einer anderen eindeutigen Datei. Angenommen, wir möchten ' a.txt ' Zeile für Zeile analysieren, den Pfad im Zeichenfolgenformat extrahieren und dann ein Tool wie vim verwenden, um die Datei unter diesem Pfad zu verarbeiten, und so weiter.

Nachdem Sie diesen Thread durchgearbeitet haben - Lesen Sie a Datei Zeile für Zeile den Wert einer Variablen zuweisen, schrieb ich das folgende Skript, sagen ' open-file.sh ' auf bash (ich bin neu darin)

#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
  vim -c ":q" -cq $line # Just open the file and close it using :q 
done < "$1"

Wir würden dann das obige Skript ausführen als -

./open-file.sh a.txt

Das Problem ist, dass, obwohl der Pfad zu einer neuen Datei korrekt durch $ line angegeben ist, vim beim Öffnen der Datei weiterhin den in ' a.txt ' enthaltenen Text als Befehl empfängt. Wie kann ich ein Skript schreiben, in dem ich den Pfad von ' a.txt ' korrekt abrufen, mit vim öffnen und dann die verbleibenden Zeilen in ' a.txt '?

2
V-Red 18 Jän. 2019 im 00:55

3 Antworten

Beste Antwort

Ersetzen:

vim -c ":q" -cq $line

Mit:

vim -c ":q" -cq "$line" </dev/tty

Die Umleitung </dev/tty weist vim an, die Standardeingabe vom Terminal zu übernehmen. Ohne dies ist die Standardeingabe für vim "$1".

Es wird auch empfohlen, $line in doppelte Anführungszeichen zu setzen, um es vor Wortaufteilung usw. zu schützen.

Während vim hervorragend für interaktives Arbeiten geeignet ist, sollten Sie, wenn Ihr Endziel die vollautomatische Verarbeitung jeder Datei ist, möglicherweise Tools wie sed oder awk in Betracht ziehen.

2
John1024 17 Jän. 2019 im 22:31

Obwohl ich mir Ihres endgültigen Ziels nicht sicher bin, führt dieser Shell-Befehl vim einmal pro Zeile in a.txt aus:

xargs -o -n1 vim -c ':q' < a.txt

Wie in den Kommentaren zu erläutert, lesen Sie a Wenn Sie den Wert einer Variablen Zeile für Zeile zuweisen, tritt das Problem auf, weil vim ein interaktives Programm ist und daher weiterhin Eingaben von $line liest.

0
telenachos 17 Jän. 2019 im 22:41

Das Problem wurde bereits in erwähnt einen Kommentar unter der Antwort, auf der Sie Ihr Skript basieren.

vim verbraucht stdin, das von done < $1 an die Schleife übergeben wird. Wir können das gleiche Verhalten im folgenden Beispiel beobachten:

$ while read i; do cat; done < <(seq 3)
2
3

<(seq 3) simuliert eine Datei mit den drei Zeilen 1, 2 und 3. Anstelle von drei stillen Iterationen erhalten wir nur eine Iteration und die Ausgabe 2 und 3.

stdin wird nicht nur an read im Kopf der Schleife übergeben, sondern auch an cat im Hauptteil der Schleife. Daher liest read eine Zeile, die Schleife wird eingegeben, cat liest alle verbleibenden Zeilen, stdin ist leer, read hat nichts mehr zu lesen, die Schleife wird beendet.

Sie können das Problem umgehen, indem Sie etwas nach vim umleiten. Es gibt jedoch einen noch besseren Weg. Sie brauchen die Schleife überhaupt nicht:

< "$1" xargs -d\\n -n1 vim -c :q -cq

xargs führt vim einmal für jede Zeile in der von $1 angegebenen Datei aus.

0
Socowi 18 Jän. 2019 im 09:46