Solo  当前访客:3 开始使用


Shell脚本的书写

最近的一个项目中,一直在追查Kafka读取数据的问题。在monitor工具中会列出每个partition的消费者的IP,另一方面每台机器消费了多少数据能拿到的只有host name。如何从这些ip映射到host name,并分析每个机器所处的cluster有多少台机器,消费多少个partition做一些简单分析的自动化脚本。因此又重新倒腾了下shell脚本。
对shell脚本不熟悉的同学看来,shell只是一系列的命令,但是只有真正熟悉之后,才能了解到它的强大,尤其是对文本\文件的各种便利化处理,以及它天生更linux系统结合的特性,使它成为一种高效的脚本利器。
本篇文章回顾了写好shell脚本需要了解的几个基本元素,几乎每个脚本都需要用到的一些基本知识。

1. Usage函数

Usage函数描述一个shell脚本的用途,描述可以使用的参数,以及给出一些简单的运行命令样本。

function usage() {
    echo "$0 [-a]"
    echo "Usage: "
    echo -e "\t Get dns name for each host from IP"
    echo -e "\t -a Analysis the count of hosts for each cluster"
    echo -e "\t -h Print help message"
    echo -e "Sample: $0  Running command without any argument will check host name for each ip and print in console"
    echo -e "Sample: $0 -a  Running command to further analysis the hosts number for each cluster"
}

说明:

  1. $0的作用是显示当前的脚本路径名字
  2. echo -e中-e的作用是为了输出制表符,如果没有-e会直接输出"\t"

2. 脚本的参数传递

虽然shell脚本提供了简单的数字偏移来获取每个参数, 如$1用来获取第一个参数,但是如果有多个参数,这样传递就不够清晰,容易产生传递错误(尤其当有个参数为空的时候,会把下一个参数当成当前参数)。因此一个好的参数传递,推荐使用getopts。

while getopts ":ah" opt
do
    case ${opt} in
        a)
        analysis
        ;;
        h)
        usage
        ;;
        ?)
        usage
    esac
done

说明:

  1. getopts里面的参数分为两种,一种无需带参数,如本例中的h和a,都是不需要参数的。如果需要传入参数,比如-n Devin, 需要传入参数的话,在参数n后面加“:", 比如":n:ah".
  2. ?表示没有匹配到的参数。
  3. 开头“:",表示会屏蔽掉需要传参数的没有传参数的错误。

3. 字符串的处理

shell里面所有数据的基本形式,都是字符串,因此懂得字符串常用的处理方式对于shell脚本来说至关重要。

3.1 获取最后一个字符

对于字符串的截取,shell提供了一套非常方便方式,以取值"{}"来获取。

function get_last_char() {
    name=$1
    echo ${name: -1}
}

说明:

  1. name是一个字符串变量名,-1表示截取最后一个字符。更一般的写法是${var:0:5},表示从左边第一个字符开始,截取5个字符长度。如果一直到最后,可以省略“:5"。 如果从右边起则在表示位置的数字前加“0-”,如${var:0-15:10}表示从右边倒数第15个字符开始截取10个字符。

3.2 字符串的替换

sed是字符串处理的利器,可以用它来进行文本替换非常方便。

echo "https://wudevin.cn." | sed 's/.$//g'

说明:

  1. 上述命令的作用是去掉文本中最后一个“."(位于cn后)。
  2. ".$"中$的作用表示行末。g表示全局替换。
    更多sed命令的用法,参照:https://www.runoob.com/linux/linux-comm-sed.html

3.3 字符串分割

awk是最常用的场景是用来获取其他命令输出结果的某一些字段。一般文本的组织都有一定的格式,如csv是以“,"作为文本的分割符。如果从这些以一定分隔符分割开来的文本中,获取想要的字段呢?这就是这个命令的用武之地。

echo "Wu Devin" | awk -F\  '{print $NF}'

说明:

  1. 上述命令的输出为:Devin。awk的-F参数是用来指定分隔符,这里指定分隔符是空格。但是空格是特殊字符,所以用了转义字符""。
  2. print里面的作用是选取你想要的column。 NF表示最后一个column。当然你也可以用数字, 1表示第一个column,2表示第2个column,以此类推。0表示整个文本。

4. 流程控制

4.1 条件表达式

条件表达式,也就是最基本的表达式if。

if [ -z "$var" ]  
then  
 echo "\$var is empty"  
else  
 echo "\$var is NOT empty"  
fi

说明:

  1. 上述表达式的作用是判断字符串是否为空,然后走不同的分支。

4.2 循环迭代表达式

最常见的方式,为在一个数组中迭代。

    clusters=("d12" "d13" "d14" "c1" "c2")
    for cluster_name in "${clusters[@]}" ; do
        if [[ ${cluster_name} == c* ]]; then
            analysis_c_cluster ${cluster_name}
        else
            analysis_d_cluster ${cluster_name}
        fi
    done

5. 文件处理

5.1 写入文件

往文件里面以覆盖的方式写入数据

echo "something write to file" > fileName.txt

往文件里面以追加的方式写入数据

echo "something write to file" >> fileName.txt

5.2 从文件读取数据

可以跟for表达式结合起来,每次读取处理一行数据。

    for host in `cat host.txt` ; do
        echo "line: ${host})"
    done

标题:Shell脚本的书写
作者:wuhaifengdhu
地址:https://wudevin.cn/articles/2019/12/01/1575210308906.html
只有站在峰顶的人,才能看见星辰大海。
标签:
新一篇: 离线环境下搭建python运行环境 旧一篇: 0到7能组成多少个不重复的4位偶数