.txt
ファイル名を引数として取り、ファイル行を読み取るスクリプトを作成しようとしています。行ごとに、各行をコマンドに渡します。たとえば、command --option "LINE 1"
を実行してから、command --option "LINE 2"
などを実行します。コマンドの出力は別のファイルに書き込まれます。どうすればよいですか?どこから始めればよいのかわかりません。
回答
while read
ループを使用します:
: > another_file ## Truncate file. while IFS= read -r LINE; do command --option "$LINE" >> another_file done < file
もう1つは、ブロックごとに出力をリダイレクトすることです:
while IFS= read -r LINE; do command --option "$LINE" done < file > another_file
最後はファイルを開くことです:
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
コマンドの1つが入力を読み取る場合、それは良いことですコマンドがそれを食べないように、入力に別のfdを使用するというアイデア(ここでは、ksh
、zsh
、またはbash
-u 3
の場合は、代わりに<&3
を移植可能に使用します):
while IFS= read -ru 3 LINE; do ... done 3< file
フィン引数を受け入れるには、次の操作を実行できます。
#!/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"
次のように実行できます:
bash script.sh file another_file
追加のアイデア。 bash
では、readarray
を使用します:
readarray -t LINES < "$FILE" for LINE in "${LINES[@]}"; do ... done
注:IFS=
は、行の値の先頭と末尾のスペースを削除してもかまわない場合は省略できます。
回答
別のオプションはxargs
です。
GNU xargs
の場合:
xargs -a file -I{} -d"\n" command --option {} other args
{}
はテキスト行のプレースホルダーです。
その他のxargs
には通常-a
、-d
はありませんが、-0
NULで区切られた入力の場合。これらを使用すると、次のことができます。
< file tr "\n" "\0" | xargs -0 -I{} command --option {} other args
Unix準拠のシステム(-I
はPOSIXではオプションであり、 UNIX準拠のシステムに必要)、「xargs
で期待される形式で行を引用するための入力を前処理する必要があります:
< file sed "s/"/"\\""/g;s/.*/"&"/" | xargs -E "" -I{} command --option {} other args
ただし、一部のxargs
実装では、引数の最大サイズに非常に低い制限があることに注意してください(たとえば、Solarisでは255、 Unix仕様で許可されている最小値)。
コメント
回答
正確に保つ質問へ:
#!/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
コメント
- 魅力のように機能しました:-)
- +1はこれを気に入りました、ありがとう
回答
私が選んだベストアンサーund is:
for i in `cat`; do "$cmd" "$i"; done < $file
編集:
… 4年後…
何度か反対票を投じ、さらに経験を積んだ後、今すぐ次のことをお勧めします:
xargs -l COMMAND < file
コメント
- これにより、ファイル内の 単語 ごとに1回コマンドが呼び出されます。また、理由がない限り、シェル変数への参照は常に引用する必要があります(
do "$cmd" "$i";
のように)。ファイルに*
が単語として含まれている場合、コードは$cmd *
を実行します。もちろん、次のコマンドを実行します。現在のディレクトリ内のファイルのリスト。 - @ G-Man、ただし
zsh
、`cat`
を除くすでに*
を展開します(引用符で囲まれていない$i
は、はいくつかを紹介します)。いずれにせよ、そのアプローチは確かに間違っています。 - +1。各行にスペースなしで使用されているコマンドに必要な入力のみが含まれている場合、これは正常に機能します。
- + 1、xargsソリューションが気に入りました
- これは機能しています! (後で
xargs -l COMMAND < file
を編集します)。ありがとう!
回答
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
出力
--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
回答
ed file.txt %g/^/s// / 2,$g/^/-,.j 1s/^/command/ wq chmod 755 file.txt ./file.txt
すべてのファイルの行を1つのコマンドに引数として渡します。つまり、
command line1 line2 line3 ....
--option
が必要な場合各行の前にフラグを立てて、2番目のコマンドを次のように変更します。
%g/^/s// --option /
コメント
- -1 for edを使用しています…本当に?
- 私はあなたに反対票を投じませんでした'しかし、おそらく次の理由がありました:(1)これはしません質問が求めるもの。これにより、コマンドラインにファイルのすべての内容が含まれるコマンドが1回呼び出されます。 1行に1回ではなく。(2)これは、シェルに固有の文字(ファイル内にある可能性がある)を処理するために何もしません。 例:
'
、"
、<
、>
、;
など(3)これにより不要な一時ファイルが作成されます。 (4)このようなことは、一般的に「ヒアドキュメント」で行われます。 (5)ed
コマンドが不器用です。 最初の2つのコマンドは、%s/^/ /
と%j
に減らすことができます。
<file xargs -L 1 -I{} command --option {} other args
に削減可能