while ループと if ステートメントは、条件が満たされると異なるコマンドを実行します。

while ループと if ステートメントは、条件が満たされると異なるコマンドを実行します。

~へfile.txt

chicken sheep cow  
tomato cucumber  
banana

if声明なし

while read -r column1 column2 column3; do  
    command  
done < file.txt

ステートメントを使用すると、if行に3つの列がある場合は何を行います。2つの列がcommand1ある場合はcommand2どうすればよいですかcommand3

答え1

または他の方法あなたの例と最小の違いは次のとおりです。

#!/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すべての前後のスペース文字はデフォルトで削除されます。

入力に3つ以上の列が含まれている場合、3番目以降の列のすべてのデータはcolumn3

バラよりファイル(データストリーム、変数)を1行ずつ(および/またはフィールドごとに)読み取る方法は?

答え2

各行を配列として読み込み、次を使用して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

答え3

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

答え4

ホクラキンの答え位置パラメータを設定し、各反復で対応する数量を評価することによって評価を使用するための良いアイデアがすでにあります。テーマの変更は、bashまたはの配列を使用して行うことができますksh(実際に位置パラメータを維持したい場合にも便利です)。以下の例は for ですbash(in の代わりに for または in を使用でき、kshもちろん行を変更することもできます)。mksh-A-aread#!

#!/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

関連情報