IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    运维工程师|数据库工程师|shell脚本常用知识

    Vlix_Liu发表于 2015-11-30 16:10:59
    love 0

     

    作为一个运维工程师(数据库工程师) ,管理和维护成百上千台服务器是很正常的事情,脚本就成为了
    不可或缺的工具,shell是最基本的了,工作中经常用到,自己讲偶尔犯错的部分记录一下,警示自己。
    另外,shell 是Linux原生的交互工具,使用方便,简单,可以在运维工作中 ,大大的提高工作效率
    ,对日常简单的任务都可以由shell处理 , 哈哈 。 当然也有不合适的地方。比如说:

    需要比数组更复杂的数据结构
    出现了复杂的转义问题
    有太多的字符串操作 
    性能问题
    任务代码比较多 ... 
    注意 : 这个时候 选择 Python  会是一个明智的选择
    

    shell 工作中易错总结

    1.字符串单引号和双引号 ‘’ “”

    a. 单引号内部的 变量 是完全按照字符展示的,不会替换成为变量的值的。
    b. 双引号中的变量会进行变量值替换。

    #!/bin/bash
    for x in $( seq 1 10 )
    do
    echo '$x : ' ," $x !"
    done
    

    输出:

    $x :  , 1
    $x :  , 2
    $x :  , 3
    $x :  , 4
    $x :  , 5
    $x :  , 6
    $x :  , 7
    $x :  , 8
    $x :  , 9
    $x :  , 10
    

    2. 反引号和$()的使用

    和 $() 是对等的,但是后者更清晰,特别是多层次嵌套的时候。 反单引号在有些字体里
    跟正单引号很相似。 $()能够内嵌使用,而且避免了转义符的麻烦。

    for x in $( seq 1 10 ) 和 for x in `seq 1 10 ` 是对等的
    

    比如要是 输出 : 1-2-3-4 。 明显第二个更加简单方便,并且不需要转义

    echo "1-`echo 2-\`echo 3-\\\`echo 4\\\`\``"
    echo "1-$(echo 2-$(echo 3-$(echo 4)))"
    

    3. 从文件中按照行级别读取

    以下三个方式都可以的
    3.1 while

    while read line
    do
        echo $line
    done < test
    

    3.2 cat | while

    cat filename | while read line
    do
        echo $line
    done
    

    3.3 for
    注意 此方式在行中有空格的时候 会变为多行

    for line in `cat filename `
    do
        echo $line
    done
    

    4. 变量 variable

    整数变量加减乘除运算 , 这个我经常记混,所以特别记录以下

    for x in ` seq 1 10 ` 
    do
        echo $x "   "  $((${x} + 10)) " " $(($x * 10))
    done
    

    输出 :
    1 11 10
    2 12 20
    3 13 30
    4 14 40
    5 15 50
    6 16 60
    7 17 70
    8 18 80
    9 19 90
    10 20 100

    5. function ,shell 定义函数非常方便

    把相同的功能模块定义为function , 可以提高代码的重用性和可读性,如下读取文件代码 :

    GetFileLines() {     
        local sum=0
        local line=””
        while read line ; do
            sum=$((${sum} + ${line}))
        done
        echo ${sum}
    } 
    

    6. 用[]替代[]

    使用[[]]能避免像异常的文件扩展名之类的问题,而且能带来很多语法上的改进
    ,而且还增加了很多新功能:

    操作符 功能说明
    ||          逻辑or(仅双中括号里使用)
    &&          逻辑and(仅双中括号里使用)
    <           字符串比较(双中括号里不需要转移)
    -lt         数字比较
    =           字符串相等
    ==          以Globbing方式进行字符串比较(仅双中括号里使用,参考下文)
    =~          用正则表达式进行字符串比较(仅双中括号里使用,参考下文)
    -n          非空字符串
    -z          空字符串
    -eq         数字相等
    -ne         数字不等
    

    单中括号:

    [ $x -gt  3 ] 
    

    双中括号

    [[ $x >  3 ]] #右侧如果是变量比较,一定要加上双引号
    
    正则表达式

    使用双中括号带来的好处用下面几个例子最能表现:

    t="abc123"
    [[ "$t" == abc* ]]         # true (globbing比较)
    [[ "$t" == "abc*" ]]       # false (字面比较)
    [[ "$t" =~ [abc]+[123]+ ]] # true (正则表达式比较)
    [[ "$t" =~ "abc*" ]]       # false (字面比较)
    

    注意,从bash 3.2版开始,正则表达式和globbing表达式都不能用引号包裹。如果你的表达式里有空格
    ,你可以把它存储到一个变量里:

    r="a b+"
    [[ "a bbb" =~ $r ]]        # true
    

    按Globbing方式的字符串比较也可以用到case语句中:

    case $t in
    abc*)  <action> ;;
    esac
    

    7. 字符串操作

    ${#string}                              $string的长度 
    ${string:position}                      从位置$position开始提取子串
    ${string:position:length}               从位置$position开始,长度为$length的子串
    ${string#substring}                     从开头, 删除最短匹配$substring的子串
    ${string##substring}                    从开头, 删除最长匹配$substring的子串
    ${string%substring}                     从结尾, 删除最短匹配$substring的子串
    ${string%%substring}                    从结尾, 删除最长匹配$substring的子串
    ${string/substring/replacement}        $replacement,替换第一个匹配的$substring
    ${string//substring/replacement}       $replacement, 代替所有匹配的$substring
    ${string/#substring/replacement}       $string的前缀匹配$substring ,替换
    ${string/%substring/replacement}       $string的后缀匹配$substring, 替换
    

    Bash里有各种各样操作字符串的方式
    基本用户

        f="path1/path2/file.ext" 
        len="${#f}" # = 20 (字符串长度) 
        # 切片操作: ${<var>:<start>} or ${<var>:<start>:<length>}
        slice1="${f:6}" # = "path2/file.ext"
        slice2="${f:6:5}" # = "path2"
        slice3="${f: -8}" # = "file.ext"(注意:"-"前有空格)
        pos=6
        len=5
        slice4="${f:${pos}:${len}}" # = "path2"
    

    替换操作

    f="path1/path2/file.ext" 
    single_subst="${f/path?/x}"   # = "x/path2/file.ext"
    global_subst="${f//path?/x}"  # = "x/x/file.ext" 
    

    删除头部或尾部

    f="path1/path2/file.ext"
    # 删除字符串头部
    extension="${f#*.}"  # = "ext"
    # 以贪婪匹配方式删除字符串头部
    filename="${f##*/}"  # = "file.ext"
    # 删除字符串尾部
    dirname="${f%/*}"    # = "path1/path2" 
    # 以贪婪匹配方式删除字符串尾部
    root="${f%%/*}"      # = "path1"
    

    8.分割字符串

    假设变量$str的值为foo-bar-baz,如果你想按-分割成多个段并遍历它,可以使用read命令,
    并且设置 IFS 的值为-:

    $ IFS=- read -r x y z <<< "$str"
    

    这里我们使用read x命令从标准输入读取内容,分割后并依次保存到x y z变量中。其中,$x 为foo,
    $y 为 bar, $z 为 baz。 另外要留意的一处是here-string操作符<<<,可以很方便地将字符串传递
    给命令的标准输入。在这个例子中,$str的内容传给 read 命令的标准输入。

    你也可以将分割后的几个字段保存到数组类型的变量中:
    $ IFS=- read -ra parts <<< "foo-bar-baz"
    

    在这里,-a 选项告诉read命令将分割后的元素保存到数组parts中。随后,你可以通过${parts[0]}
    ${parts[1]}和${parts[0]}来访问数组的各个元素,或者通过${parts[@]}来访问所有元素。

    9. 转换大小写

    使用tr 命令替换
    

    10.去除行尾的最后一个字符

    awk -F "" -v OFS=""  '$NF="" {print}1'
    

    总结

    shell 使用比较方便,系统原生,属于轻量级脚本,但是不得不承认,语法上面不如Python 简洁,另外shell 用起来很多地方容易出错。


沪ICP备19023445号-2号
友情链接