ファイルから2つの変数を抽出するシェルスクリプトを作成しており、以下のFORループを使用しました。
for i j in `cat list`
do
echo title
echo total "$i" "," "$j"
echo end
done
猫のリストどこか
AAA 111
BBB 222
CCC 333
予期しない「j」エラーが発生しました。 「whileループ」を使用しましたが、運がありませんでした。
予想される出力は次のとおりです。
title
total AAA,111
total BBB,222
total CCC,333
end
答え1
for
実際にもループも必要ありません。while
次のいずれかのコマンドがawk
機能します。
awk 'BEGIN {print "title"}
{print "total",$1","$2}
END {print "end"}' list
または:
awk 'BEGIN {print "title"}
{printf "total %s,%s\n", $1, $2}
END {print "end"}' list
ファイルのデータを読み取る前に、BEGIN{print "title"}
単語を一度印刷します。title
{print "total",$1","$2}
total
列の値の間のスペースを表す引用符のないカンマの後に単語を印刷し、列自体を印刷します。このブロックは各入力行に対して実行されます。
END{print "end"}
end
ファイルの単語と終わりを印刷します。 END はファイルから最終入力を読み取った後、ブロックを実行するよう指示します。
2番目のコマンドの場合:
唯一の違いは次のとおりです。
{printf "total %s,%s\n", $1, $2}
これは、型が定義されている場所のprintf
代わりにprint
最初のパラメータを使用します。
%s,%s
との値をカンマで区切って印刷し、次の行に移動する$1
には、新しい行を表し、ファイルの最後までとの値を印刷するように指示します。$2
\n
$1
$2
個人的には、引用符とコンマのprintf
両方を使用するのではなく、単一の引用符セットのみを使用できるため、2番目のコマンドを使用します。total
また、マニュアルページを読んでみるとわかるように、さらにモジュール化されています。 2つの異なる方法を示すために、2つのコマンドのみを含めました。
出力
title
total AAA,111
total BBB,222
total CCC,333
end
答え2
あなたはそれを使用することができますwhile read
:
echo "title"
while read -r i j
do
echo total "$i,$j"
done < list
echo "end"
出力は次のとおりです。
title
total AAA,111
total BBB,222
total CCC,333
end
答え3
特定の問題は、テキスト処理ユーティリティを使用するとよりよく解決することができますが、awk
@Nasirが示したように(あなたも見ることができますシェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?) タイトルの質問にお答えします。
構文はfor i j in words...; do something with $i and $j; done
まだzsh
サポートされていませんbash
。
またbash
、分割(必要なもの)とワイルドカード(望ましくないもの)`cmd`
(変換したい古いコマンドの代替形式$(cmd)
)を実行し、zsh
期待どおりに分割します。
bash
別のPOSIX様シェルを使用して一度に2つの単語を処理するには、for i j in words...
次のようにします。
set -- words...
while [ "$#" -gt 0 ]; do
i=$1 j=$2 # or j=${2-missing}
something with "$i" and "$j"
shift "$(( 2 - ($# == 1) ))"
done
あなたの場合はset
次のとおりです。
set -o noglob # disable globbing
set -- $(cat list)
(修正がないと仮定すると、デフォルトでは$IFS
スペース、タブ、改行が含まれます)。