コマンドの引数としてテキストファイルの各行を解析するにはどうすればよいですか?

.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を使用するというアイデア(ここでは、kshzsh、または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仕様で許可されている最小値)。

コメント

  • <file xargs -L 1 -I{} command --option {} other args
  • に削減可能

  • @iruvar、いいえ、引用符を処理して空白を削除します。

回答

正確に保つ質問へ:

#!/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に減らすことができます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です