標準入力のデータを改行文字で区切られた引数として受け取るスクリプトがあります。
string1,string2
string3,string4
string1,string2
とは別に持ちたいですstring3,string4
。しかし、不明な数のそのような行を受け取り、私のスクリプトは最初の2行だけを読んでから停止します。標準入力で解析しようとしましたが、\n
動作しません。この問題にどのように対処する必要がありますか?
私はこのように読もうとする
for i in "$@"
do
var1=$(echo "$i" | cut -f2 -d,)
var2=$(echo "$i" | cut-f2 -d,)
#etc
input.txt
私が実際に達成したいのは、次のタイプの入力を含むファイルがあると仮定することです。
string1,string2
string3,string4
これにより、文字列の行数に関係なく各行を取得し、両方の変数から別々に抽出したいとcat input.txt | ./myscript.sh
思います。stringI,stringJ
答え1
テキスト処理を実行したい場合は、最も明確な方法は、awk
この目的のために特別に設計されたものを使用することです(または使用することもできますperl
)。sed
awk -F, '{print "something with "$1" and "$2}'
入力が実際のCSVの場合、次のようにより複雑な値を持つことができます。
"field, with comma" , "and with
newline", "or ""quotes"""
専用のcsv解析ユーティリティを使用perl
したい場合があります。python
たとえば、これらのフィールドを引数として使用して特定のコマンドを実行する必要があるため、これらのフィールドをシェル変数として指定する必要がある場合は、次のようにします。
while IFS=, read -r a b rest; do
something-with "$a" "$b"
done
GNUparallel
並列実行も参照してください。
PARALLEL_SHELL=sh parallel -C, 'something-with {1} {2}'
しかし、GNUはparallel
かなりのオーバーヘッドを引き起こすので、並列化はそれほど価値があるはずです。
シェルはksh93
実際にCSV形式を理解します(上記の複雑な例のように個々のフィールドへの参照を処理します)。
while IFS=, read -rS a b rest; do
do-something-with "$a" "$b"
done
答え2
複数行のユーザー入力を取得するには、-dオプションを指定してreadを使用することをお勧めします。
または、tr '\n' ' '
新しい行を空白に変換する方法を使用します。これはかなりハッキーです。
私は方法がわかりませんが、trを使用してEOFを新しい行に変換すると、期待どおりに完全に実行できます。
より具体的な情報が必要な場合はコメントを残してください。
答え3
(何らかの理由で)すべての入力ラインを配列に配置するには、bashで次のように使用できます。
readarray -t input_lines
その後、各行はインデックス配列の要素として保存されますinput_lines
。-t
各行から改行文字を削除することです。