file.txt
の中
chicken sheep cow
tomato cucumber
banana
if
ステートメントなし
while read -r column1 column2 column3; do
command
done < file.txt
if
ステートメントを使用して、行に3つの列がある場合はcommand1
を実行し、2つの列がある場合はcommand2
を実行し、1つの列しかない場合はcommand3
を実行する方法
または他のアプローチあなたの例の最小の違い:
#!/bin/bash
while read -r column1 column2 column3; do
if [ -z "$column2" ] ; then
printf '%s\n' "Only first column has data"
Elif [ -z "$column3" ]; then
printf '%s\n' "Only first and second columns has data"
Elif [ -n "$column3" ]; then
printf '%s\n' "All three columns has data"
fi
done < file.txt
出力は次のようになります。
All three columns has data
Only first and second columns has data
Only first column has data
メモ:
この例では、1行目と2行目の末尾にいくつかのスペースが含まれていますが、デフォルトでは、read
はすべての先頭と末尾のスペース文字を削除します。
入力に4つ以上の列が含まれている場合、3番目の列以降のすべてのデータはcolumn3
に配置されます
ファイル(データストリーム、変数)を行ごと(および/またはフィールドごと)に読み取るにはどうすればよいですか? を参照してください。
read -ra
を使用して各行を配列に読み込み、配列サイズを確認できます。
fmt="Number of fields: %s. The last one: %s\n"
while read -ra items; do
if [ ${#items[*]} == 3 ]; then
printf "$fmt" ${#items[*]} ${items[-1]}
Elif [ ${#items[*]} == 2 ]; then
printf "$fmt" ${#items[*]} ${items[-1]}
Elif [ ${#items[*]} == 1 ]; then
printf "$fmt" ${#items[*]} ${items[-1]}
fi
done < file.txt
もちろん、式printf "$fmt" ${#items[*]} ${items[-1]}
はデモのためだけに使用されたので、独自に定義できます。
上記のアプローチでは(例として)出力されます:
Number of fields: 3. The last one: cow
Number of fields: 2. The last one: cucumber
Number of fields: 1. The last one: banana
while read -r column1 column2 column3; do
if [ -z "$column2" ]; then
# one column
: command
Elif [ -z "$column3" ]; then
# two columns
: command
else
# three columns
: command
fi
done < file.txt
または
while read -r column1 column2 column3; do
set -- $column1 $column2 $column3
case $# in
1)
: command
;;
2)
: command
;;
*)
: command
;;
esac
done < file.txt
Hauke Lagingの回答 は、位置パラメータを設定して評価を使用し、反復ごとにその数を評価するという優れたアイデアをすでに持っています。テーマのバリエーションは、bash
またはksh
の配列を使用して行うことができます(位置パラメーターを保持したい場合にも便利です)。以下の例はbash
の場合です(ksh
またはmksh
の場合は-A
insead of -a
in read
、そしてもちろん変更#!
行):
#!/usr/bin/env bash
line_counter=1
while read -r -a arr;
do
case "${#arr[@]}" in
1) printf "One column in line %d\n" "$line_counter";;
2) printf "Two columns in line %d\n" "$line_counter";;
3) printf "Three columns in line %d\n" "$line_counter";;
*) printf "More than 3 lines in line %d\n" "$line_counter";;
esac
((line_counter++))
done < input.txt
そして出力は次のようになります:
$ ./eval_columns.sh
Three columns in line 1
Two columns in line 2
One column in line 3