私はbashシェルスクリプトを学んでおり、awkなどではなく純粋なbashメソッドを探しています。
情報に基づいて式を作成できるように、forループを使用して端末にパラメータとして送信された2つのファイルの内容を繰り返すことを試みます。
ファイルの内容はタブで区切られます。このファイルには拡張子がありません。以下は、評価するファイル情報のタイプの例です。
$cat file1
1 2 3
40 50 60
$cat file2
10 20 30
40 50 60
私が書いたコードは次のとおりです。
read line1 < "file1"
read line2 < "file2"
difference=0
#I can see the contents of file1 with the below code and by changing the code
#slightly I can see the contents of file2 as well using the following code:
for index1 in $line1
do
echo "The contents of index1 are: $index1"
done
#But I am trying to do something like this which isn't working:
for index1 in $line1, index2 in $line2
do
difference=$(expr $index1 - $index2)
echo $difference
done
答え1
確かに可能ですが、楽しくありません。実際には、物事に異なるアプローチをしたいと思います。
これらの特定のファイルとこの操作の場合、このスクリプトはおそらく最も単純で、while
ループの代わりに単一のループを使用しますfor
。
exec 3<file2
while read a1 a2 a3 && read b1 b2 b3 <&3
do
echo $((a1 - b1))
echo $((a2 - b2))
echo $((a3 - b3))
done < file1
各ファイルは固定された3列構造で、すべてのファイルを一度に読み込みます。file2
ファイル記述子3で開く(exec 3<file2
)独立して読むことができますfile1
。作成した内容はファイルを開いて読み込みます。最初毎回並んでください。このread
コマンドは最初の単語をにx1
、2番目の単語をにx2
、残りの行を `x3に入れます。
両方のリストを一緒に「圧着」したり、並列forループを作成したりする組み込みまたは比較的簡単な方法はありません。単純な配列や文字通りの単語リスト以外の項目の for ループは不可能になりにくく、正しい配列を構築するには、他の作業を実行するよりも多くの作業が必要です。
列数が可変であれば、これはより難しいですが、次のものを使用できます。mapfile
行から配列を作成し、通常の配列処理を使用します。C型for
ループ各行に対して、次の操作を行います。
while read line1 && read line2 <&3
do
mapfile -d $'\t' a1 <<<"$line1"
mapfile -d $'\t' a2 <<<"$line2"
for ((i=0; i<${#a1[@]}; i++))
do
echo $((a1[i] - a2[i]))
done
done <file1
a1
これにより、次を含む2つの配列がa2
作成されます。タブ区切り要素一行に、行の長さだけ繰り返しますfile1
(他のファイルの追加項目は無視されます)。
zip
ファイルの形式が正しく、列番号がその行と一致すると仮定すると、最も一般的な近似は似ていますwhile read a b ... done < <(paste <(printf '%s\n' $(<file1)) <(printf '%s\n' $(<file2)))
。これは本当に嫌なことです。
言い換えれば、シェルスクリプトは、このタイプの処理に適したメカニズムではありません。一方、awk(またはより良い場合は適切な言語)は、これよりも適切で壊れやすいです。
上記のスクリプトを見ると、実装が複雑すぎて壊れやすくなり、言語がそのために設計されていないため、従うのが難しいことがわかります。このスクリプトはもっと同じ目標を達成する他の方法よりも読みやすく、特に意味はありません。