web-dev-qa-db-ja.com

while-loopとif-statementは、条件が満たされた場合に異なるコマンドを実行します

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を実行する方法

3
Hidayats

または他のアプローチあなたの例の最小の違い:

#!/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に配置されます

ファイル(データストリーム、変数)を行ごと(および/またはフィールドごと)に読み取るにはどうすればよいですか? を参照してください。

3
Egor Vasilyev

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
1
RomanPerekhrest
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
1
Hauke Laging

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
0