shell编程 - for循环

流程控制:for循环

for循环在循环期间只关注序列处理逻辑,是一种在bash脚本编程中十分流行的循环控制结构。

新版bash语言中,for命令存在两种形式。

for:传统shell形式

原始的for命令语法结构:

for variable [in words];do
        commands
done

 其中,variable是一个在循环执行时会变化的变量名,words是一系列按顺序赋给变量variable的可选项,commands部分是每次循环都需要执行的命令块。

for i in A B C D E F G;do echo $i;done

for循环真正强大的功能在于创建字符列表的方式有很多种。

花括号扩展 

for i in {A..D};do echo $i;done

路径名扩展 

for i in *.sh;do echo $i;done

命令扩展 

#!/bin/bash

# longest-word: find longest string in a file

while [[ -n $1 ]];do
        if [[ -r $1 ]];then
                max_word=
                max_len=0
                for i in $(strings $1);do
                        len=$(echo $i | wc -c)
                        if ((len > max_len));then
                                max_len=$len
                                max_word=$i
                        fi
                done
                echo "$1: '$max_word' ($max_len characters)"
        fi
        shift
done

 上面脚本功能是在一个文件中搜索最长的字符串。当在命令行中输入一个或者多个文件名时,使用strings程序,并在每个文件中产生一个可读文本“字符”。for循环按顺序处理每个字符串,判断当前的字符串是不是迄今为止找到的最长字符串。当循环终止时,将会打印出最长的字符串和其长度。

        如果for命令中字符序列部分的选项被忽略,for循环默认处理位置参数。

#!/bin/bash

# longest-word2: find longest string in a file

for i;do
        if [[ -r $i ]];then
                max_word=
                max_len=0
                for j in $(strings $i);do
                        len=$(echo $j | wc -c)
                        if ((len > max_len));then
                                max_len=$len
                                max_word=$j
                        fi
                done
                echo "$i: '$max_word' ($max_len characters)"
        fi
done

 不带字符序列,默认遍历位置参数,文件中发现最长字符串脚本改造如上。最外层循环发生了变化,使用for代替了while。因为for命令中语句列表采用默认值,所以使用位置参数。在循环内部,前例的变量i已经被变换成变量j,并且shift也弃之不再用。

for:C语言形式

最新的bash版本加入了第二种for命令语法,类似于C语言形式。

for (( expression1; expression2; expression3 ));do
    commands
done

其中,expression1、expression2、expression3为算术表达式,commands是每次循环都要执行的命令。

就执行结果而言,for C语言形式等同于如下结构

(( expression1 ))
while (( expression2 ));do
    commands
    (( expression3 ))
done

expression1用来初始化循环条件,expression2用来决定循环何时结束,expression3在每次循环末尾执行。

#!/bin/bash

# simple_counter : demo of C style for command

for (( i=0; i<5; i=i+1 ));do
    echo $i
done

以上脚本中,expression1(i=0)对变量i初始化赋值为0,只要i的值小于5,expression2(i<5)就允许循环继续,expression3(i=i+1)在每次循环重复时使i的值增加1。

每当需要循环数值序列时候,for的C语言形式就到了用武之地。

report_home_space () {
    if [[ $(id -u) -eq 0 ]];then
        cat <<- _EOF_
                <H2>Home Space Utilization(All Users)</H2>
                <PRE>$(du -sh /home/*)</PRE>
                _EOF_
    else
        cat <<- _EOF_
                <H2>Home Space Utilization($USER)</H2>
                <PRE>$(du -sh $HOME)</PRE>
                _EOF_
    fi
    return
}

接下来将重写上述脚本,使其可以提供更多的细节,打印每个用户的文件总数和子目录总数。

report_home_space () {
    local format="%8s%10s%10s\n"
    local i dir_list total_files total_dirs total_size user_name
    if [[ $(id -u) -eq 0 ]];then
        dir_list=/home/*
        user_name="All Users"
    else
        dir_list=$HOME
        user_name=$USER
    fi
    
    echo "<H2>Home Space Utilization ($user_name)</H2>"

    for i in $dir_list;do
        total_files=$(find $i -type f | wc -l)
        total_dirs=$(find $i -type d | wc -l)
        total_size=$(du -sh $i | cut -f 1)
        echo "<H3>$i</H3>"
        echo "<PRE>"
        printf "$format" "Dirs" "Files" "Size"
        printf "$format" "----" "----" "----"
        printf "$format" $total_dirs $total_files $total_size  
        echo "</PRE>"
    done
    return
}

在函数中,加入了一些列的局部变量,并利用printf按照格式输出内容。


可以关注作者微信公众号,追踪更多有价值的内容!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值