while-loop 和 if-statement 在满足条件时执行不同的命令

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语句,如果该行有三列,它会做什么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

笔记

在您的示例中,第一行和第二行末尾包含多个空格,但默认情况下read会删除所有前导和尾随空格字符。

如果您的输入包含超过 3 列,则第三列及后续列中的所有数据将放置在column3

如何逐行(和/或逐字段)读取文件(数据流、变量)?

答案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

豪克·拉金的回答已经有了通过设置位置参数并在每次迭代中评估其数量来使用评估的好主意。主题的变化可以通过使用bashor中的数组来完成ksh(如果我们确实想保留位置参数,这也很方便)。下面的示例是 for bash(请注意,您可以使用forksh或in 代替in ,当然还要更改行):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

相关内容