テキストファイルから端末に1行に複数のパラメータを渡す

テキストファイルから端末に1行に複数のパラメータを渡す

2つのパラメータ入力ファイルと出力ファイルを必要とするPythonプログラムがあります。入力ファイルを読み込み、出力ファイルをいくつか変更してファイルのコピーを作成します。

パラメータセットを含むテキストファイルを作成しました。複数行に複数のパラメータセットがあります。ただし、プログラムを1回実行するには1行ずつ読まなければなりません。したがって、各行には、入力ファイルと出力ファイルという2つのパラメータ(スペースで区切り)が渡されます。

パラメータを含むファイルの例(これを呼び出します。line.txtごとに複数のパラメータを持つファイル):

input-file-1-path/input-file-1-name.sql output-file-1-path/output-file-1-name.sql 
input-file-2-path/input-file-2-name.sql output-file-2-path/output-file-2-name.sql
input-file-3-path/input-file-3-name.sql output-file-3-path/output-file-3-name.sql
input-file-4-path/input-file-4-name.sql output-file-4-path/output-file-4-name.sql

私はこれを試しました:

for arg in $(< /Users/Repository/File-With-Multiple-Arguments-Per-Line.txt); 
    do python /Users/Git-Repos/MyProgram.py "$arg" "$arg" ;
done. 

使い方はこんな感じです。python MyProgram.py input-file.txt output-file.txt

やるべきことをします。何らかの理由で各引数を3回処理します(したがって、入力ファイルである最初の引数も出力ファイルと見なされます。2番目の引数と同じです)。そのため、修正してはいけない入力ファイルを修正するようになりました。入力ファイルと出力ファイルが2つの別々のgitリポジトリであるため、これを知っています。

また、1つだけ使用しましたが、"$arg"私のプログラムが必要な2番目の引数(出力ファイル)を受け取っていないことを発見しました。私が見るのは私の出力ファイルではありませんが、output: <stdout> それを使用すると"$arg" "$arg"私のプログラムが誤って解釈されます。これは同じ操作を3回実行するのと同じです。最初は予想作業を完了し、2番目は出力ファイルを出力と入力として使用しました。

以下の回避策も試しましたが、私のプログラムでは何もしません。しかし、それがする必要があるように私の端末に出力を表示しますが。エラーは発生しませんでした。

参考までに:ファイルからシェルスクリプトの複数のパラメータを読み取る

while read x y; do
    python /Users/Git-Repos/MyProgram.py "$x" "$y"
done < /Users/Repository/File-With-Multiple-Arguments-Per-Line.txt

ベストアンサー1

ファイルの各行でコマンドを実行し、その行のスペースで区切られた単語を引数としてコマンドに渡しますxargs -L1

したがって、これは次のようになります。

xargs -L1 <File-With-Multiple-Arguments-Per-Line.txt python MyProgram.py

特定の形式の引用が理解されるように、xargsスペースや改行文字を含む任意のファイルパスで使用できます。ただし、引用構文はsh最新の²構文とは異なります。どちら'...'"..."二重引用符で、改行文字を含めることはできません。たとえば、次のようにできます。

tamed-input-file tamed-output-file
"Input: it's "'such a "cool" path'  'Output: Not as cool'\
'as one with'\
'newline characters'
$ xargs -L1 <a printf '1:<%s> 2:<%s>\n'
1:<tamed-input-file> 2:<tamed-output-file>
1:<Input: it's such a "cool" path> 2:<Output: Not as cool
as one with
newline characters>

xargs実装によっては、pythons stdinは読み取り専用で開かれたり(したがって)/dev/null共有されるため、stdinで読み取らないことが重要です。 GNUの実装では、次のことができます。xargsFile-With-Multiple-Arguments-Per-Line.txtpythonxargs

xargs -L1 -a File-With-Multiple-Arguments-Per-Line.txt python MyProgram.py

それを修正してください。

また、ほとんどの実装では、xargsコマンドFile-With-Multiple-Arguments-Per-Line.txtは空の場合は引数なしで一度実行されます。一部のxargs実装では、このオプションを使用してこれを回避できます-r


あなたについて:

for arg in $(< /Users/Repository/File-With-Multiple-Arguments-Per-Line.txt); 
    do python /Users/Git-Repos/MyProgram.py "$arg" "$arg" ;
done

まず、IFS分割に加えて、引用符で囲まれていないzsh部分もワイルドカードの影響を受けるため、ワイルドカードを含むファイル名に関する問題を事前に避ける必要があります。$(<...)set -o noglob

その後、ループを通過するたびに次のようになります。一つIFSで区切られ($IFSデフォルトではスペース、タブ、および改行を含む(zshではNUL))、同じ単語を2回渡しますpython。一度に2つの単語を取得するには、次の手順を実行する必要がありますzsh

for file1 file2 in $(<File-With-Multiple-Arguments-Per-Line.txt); do
  python MyProgram.py $file1 $file2
done

またはbashで:

set -o noglob
set -- $(<File-With-Multiple-Arguments-Per-Line.txt)
while (( $# > 0 )); do
  python MyProgram.py $1 $2
  shift "$(( $# < 2 ? $# : 2 ))"
done

これは、ファイルパスにスペース、タブ、または改行を含めることができないことを意味します。

同様の操作を行いxargs -L1$IFS各行にすべて別々の単語を渡すには、次の手順を実行しますzsh

while IFS= read -ru3 line; do
  python MyProgram.py $=line 3<&- # $=line for explicit IFS-splitting
done 3< File-With-Multiple-Arguments-Per-Line.txt

または:

while read -ru3 -A files; do
  python MyProgram.py $files 3<&-
done 3< File-With-Multiple-Arguments-Per-Line.txt

(置き換える必要がない限りksh93zshでも機能しますが(zshでも機能します)bashでは機能しません。)bash"${files[@]}"$files-a-A

POSIX的に:

set -o noglob
while IFS= read -r <&3 line; do
  python MyProgram.py $line 3<&- # implicit split+glob with glob disabled above
done 3< File-With-Multiple-Arguments-Per-Line.txt

それでも、任意のファイルパスは許可されません。xargs -L1dosなどの特定の形式の引用を理解する単語に行を分割するには、次のようにしますzsh

while IFS= read -ru3 line; do
  python MyProgram.py "${(Q@)${(z)line}}" 3<&- # $=line for explicit IFS-splitting
done 3< File-With-Multiple-Arguments-Per-Line.txt

ここで、zパラメータ拡張フラグは言語と同じトークン化を実行して引用符の1つのレイヤーを削除し、引用符の中に空のzshパラメータを残します(完了したように)。Q@"$@"

その後、次のものを使用できます。

"Input: it's "'such a "cool" path' $'Output: Not as cool\nas one with\nnewline characters'

¹長すぎず、一部のxargs実装では、ユーザーのロケールで有効なテキストにデコードできます。

²これはMasheyシェル(xargs1970年代後半にPWB Unixで導入されたPWBシェルとも呼ばれます)に近いです。

おすすめ記事