it-swarm.com.de

Wie übergebe ich jede Zeile einer Textdatei als Argument an einen Befehl?

Ich möchte ein Skript schreiben, das ein .txt Dateiname als Argument, liest die Datei Zeile für Zeile und übergibt jede Zeile an einen Befehl. Zum Beispiel läuft command --option "LINE 1", dann command --option "LINE 2" usw. Die Ausgabe des Befehls wird in eine andere Datei geschrieben. Wie mache ich das? Ich weiß nicht, wo ich anfangen soll.

44
WojciechF

Verwenden Sie die Schleife while read:

: > another_file  ## Truncate file.

while IFS= read -r LINE; do
    command --option "$LINE" >> another_file
done < file

Eine andere Möglichkeit besteht darin, die Ausgabe blockweise umzuleiten:

while IFS= read -r LINE; do
    command --option "$LINE"
done < file > another_file

Zuletzt öffnen Sie die Datei:

exec 4> another_file

while IFS= read -r LINE; do
    command --option "$LINE" >&4
    echo xyz  ## Another optional command that sends output to stdout.
done < file

Wenn einer der Befehle Eingaben liest, ist es eine gute Idee, ein anderes fd für die Eingabe zu verwenden, damit die Befehle es nicht essen (hier unter der Annahme von ksh, zsh oder bash für -u 3 verwenden Sie <&3 stattdessen portabel):

while IFS= read -ru 3 LINE; do
    ...
done 3< file

Um schließlich Argumente zu akzeptieren, können Sie Folgendes tun:

#!/bin/bash

FILE=$1
ANOTHER_FILE=$2

exec 4> "$ANOTHER_FILE"

while IFS= read -ru 3 LINE; do
    command --option "$LINE" >&4
done 3< "$FILE"

Welches könnte man laufen lassen als:

bash script.sh file another_file

Extra Idee. Verwenden Sie mit bashreadarray:

readarray -t LINES < "$FILE"

for LINE in "${LINES[@]}"; do
    ...
done

Hinweis: IFS= kann weggelassen werden, wenn es Ihnen nichts ausmacht, Zeilenwerte von führenden und nachfolgenden Leerzeichen zu trennen.

28
konsolebox

Eine andere Option ist xargs.

Mit GNU xargs:

< file xargs -I{} -d'\n' command --option {} other args

{} ist der Platzhalter für die Textzeile.

Andere xargs haben nicht -d, aber einige haben -0 für NUL-getrennte Eingabe. Mit denen können Sie tun:

< file tr '\n' '\0' | xargs -0 -I{} command --option {} other args

Auf Unix-konformen Systemen (-I ist in POSIX optional und nur für Unix-konforme Systeme erforderlich. Sie müssen die Eingabe auf quote die Zeilen in dem von xargs erwarteten Format vorverarbeiten:

< file sed 's/"/"\\""/g;s/.*/"&"/' |
  xargs -E '' -I{} command --option {} other args

Beachten Sie jedoch, dass einige xargs-Implementierungen eine sehr niedrige Grenze für die maximale Größe des Arguments haben (255 unter Solaris, beispielsweise das in der Unix-Spezifikation zulässige Minimum).

29
ctrl-alt-delor

Genau auf die Frage eingehen:

#!/bin/bash

# xargs -n param sets how many lines from the input to send to the command

# Call command once per line
[[ -f $1 ]] && cat $1 | xargs -n1 command --option

# Call command with 2 lines as args, such as an openvpn password file
# [[ -f $1 ]] && cat $1 | xargs -n2 command --option

# Call command with all lines as args
# [[ -f $1 ]] && cat $1 | xargs command --option
9
miigotu

Die beste Antwort, die ich gefunden habe, ist:

for i in `cat`; do "$cmd" "$i"; done < $file

BEARBEITEN:

... vier Jahre später ...

nach mehreren Abstimmungen und etwas mehr Erfahrung würde ich jetzt folgendes empfehlen

xargs -l COMMAND < file
5
Steffen Roller
    sed "s/'/'\\\\''/g;s/.*/\$* '&'/" <<\FILE |\
    sh -s -- command echo --option
all of the{&}se li$n\es 'are safely Shell
quoted and handed to command as its last argument
following --option, and, here, before that echo
FILE

AUSGABE

--option all of the{&}se li$n\es 'are safely Shell
--option quoted and handed to command as its last argument
--option following --option, and, here, before that echo
2
mikeserv