Linux Shell脚本攻略1:小试牛刀(3)

来源:互联网 发布:淘宝达人账号怎么取消 编辑:程序博客网 时间:2024/05/16 13:52

函数和参数


  1. 定义函数
    • function fname() { statements }
    • fname() { statements }
  2. 调用函数
    • fname
  3. 参数可以传递给函数,并由脚本进行访问
    • fname arg1 arg2
  4. 参数也可以传递给脚本并通过script:$0(脚本名)访问。
    • $1是第一个参数。
    • $n是第n个参数。
    • "$@" 被扩展成"$1" "$2" "$3"等。
    • "$*" 被扩展成"$1c$2c$3",其中cIFS的第一个字符。
    • "$@" 要比"$*"用得多。由于"$*"将所有的参数当做单个字符串,因此它很少被使用。
  5. 在Bash中,函数同样支持递归。
    • F() { echo $1; F hello; sleep 1; }
  6. Fork炸弹
    • :(){ :|:& };:
  7. 导出函数
    • 函数也能像环境变量一样用export导出,如此一来,函数的作用域就可以扩展到子进程中,如:$ export -f fname
  8. 读取命令返回值,如果命令成功退出则返回状态为0,否则为非0。
    • $ cmd; echo $?;
  9. 向命令传递参数。假设-p、-v是可用选项,-k N是另一个可以接受数字的选项,同时该命令还接受一个文件名作为参数,那么,它有如下几种执行方式:
    • $ command -p -v -k 1 file
    • $ command -pv -k 1 file
    • $ command -vpk 1 file
    • $ command file -pvk 1

将命令序列的输出读入变量


  1. 输入通常是通过stdin或参数传递给命令。输出要么出现在stderr,要么出现在stdout。当我们组合多个命令时,通常将stdin用于输入,stdout用于输出。此时,这些命令被称为过滤器(filter),我们使用管道(pipe)连接每个过滤器,管道操作符是|。如:
    • $ cmd1 | cmd2 | cmd3
  2. 我们通常使用管道并利用子shell的方式将多个文件的输出组合起来,如:
    • $ ls | cat -n > out.txt
  3. 我们可以用下面的方法读取由管道相连的命令序列的输出,这种方法被称为子shell。
    • $ cmd_output=$(COMMANDS)
    • $ cmd_output=$(ls | cat -n); echo $cmd_output;
  4. 另一种被称为反引用(也有人称反标记)的方法也可以用于存储命令输出:
    • $ cmd_output=`COMMANDS`
    • $ cmd_output=`ls | cat -n`; echo $cmd_output;
  5. 利用子shell生成一个独立的进程,可以使用()操作符来定义一个子shell:
    • $ pwd; (cd /bin; ls); pwd;
    • 当命令在子shell中执行时,不会对当前shell有任何影响;所有的改变仅限于子shell内。
  6. 通过引用子shell的方式保留空格和换行符。假如我们使用子shell或反引用的方法将命令的输出读入一个变量中,可以将它放入双引号中,以保留空格和换行符\n。如:
    image

不使用回车键来读取n个字符


  1. read是一个重要的Bash命令,它用于从键盘或标准输入中读取文本。我们可以使用read以交互的形式读取来自用户的输入。
  2. 大多数编程语言的输入库是从键盘读取输入,但只有按下回车键的时候,才标志着输入完毕。而read命令提供了一种不需要按回车键就可以读取输入的方法。
  3. 从输入中读取n个字符并存入变量variable_name:
    • $ read -n number_of_chars variable_name
  4. 用无回显的方式读取密码
    • $ read -s var
  5. 显示提示信息
    • $ read -p "Enter input:" var
  6. 在特定时限内读取输入(s)
    • $ read -t timeout var
  7. 用特定的定界符作为输入行的结束
    • $ read -d delim_char var

运行命令直至成功


有时候命令只有满足某些条件或是某种外部事件(例如文件可以被下载)操作才能够成功执行,这种情况下,我们可能希望重复执行命令,直到成功为止。

    repeat()     {    while true       # 大多数现代系统中,true是作为/bin中的一个二进制文件来实现的,因此每执行一次while循环,shell就会生成一个进程。不想这样的话,可以使用shell内建的:命令。    do         $@ && return    done     } 
    repeat()     {    while :     # : 总是会返回为0的退出码,即成功执行命令的退出码。    do         $@ && return    done    } 
    repeat()     {    while true    do        $@ && return        sleep 30    #访问网站的时候要控制频率,以防被加入黑名单。    done     }  

字段分隔符


  1. 内部字段分隔符(Internal Field Separator,IFS)是shell脚本编程中的一个重要概念。在处理文本数据时非常重要。
  2. 内部字段分隔符适用于特殊用途的定界符(delimiter),IFS是存储定界符的环境变量,它是当前shell环境使用的默认定界字符串。
  3. 考虑CSV数据的情况:
    data="name,sex,rollno,location"    oldIFS=$IFS    for item in $data;    do        echo Item: $item    done    IFS=$oldIFS
    #!/bin/bash    #用途:演示IFS的用法    line="root:x:0:0:root:/root:/bin/bash"    oldIFS=$IFS;    IFS=":"    count=0    for item in $line;    do        [ $count -eq 0 ] && user=$item;        [ $count -eq 0 ] && shell=$item;        let count++    done;    IFS=$oldIFS    echo $user\'s shell is $shell;

迭代器


对一系列值进行迭代时,循环非常有用。Bash提供了多种类型的循环。

for循环

    for var in list;   #list可以是一个字符串,也可以是一个序列。    do        commands;    done
  • echo {1..50}能够生成一个从1~50的数字列表。
  • echo {a..z}; echo {a..h};能够生成字母列表。
  • for i in {a..z}; do actions; done;

for循环也可以采用C语言中for循环的格式,如:

    for((i=0;i<10;i++))    {        commands;    }

while循环

    while condition    do        commands;    done

until循环

    x=0;    until [ $x -eq 9 ];    do        let x++; echo $x;    done

比较与测试


    if condition;    then        commands;    else if condition; then        commands;    else        commands;    fi    [ condition ] && action; #如果condition为真,则执行action;    [ condition ] || action; #如果condition为假,则执行action。    # &&是逻辑与运算发,||是逻辑或运算符。

算数比较

  1. 条件通常被放置在封闭的中括号内,一定要注意在[]与操作数之间有一个空格,如果忘记了这个空格,脚本就会报错,例如:
    • [$var -eq 0 ] or [ $var -eq 0]
  2. 对变量或值进行算术条件判断:
    • [ $var -eq 0 ] #当$var等于0时,返回真
    • [ $var -ne 0 ] #当$var为非0时,返回真
    • [ $var -gt 0 ] #当$var大于0时,返回真
    • [ $var -lt 0 ] #当$var小于0时,返回真
    • [ $var -ge 0 ] #当$var大于等于0时,返回真
    • [ $var -le 0 ] #当$var小于等于0时,返回真
  3. 可以结合多个条件进行测试
    • [ $var1 -ne 0 -a $var2 -gt 2 ] #使用逻辑与-a
    • [ $var1 -ne 0 -o $var2 -gt 2 ] #使用逻辑或-o
  4. 文件系统相关测试

    • [ -f $file_var ] # 如果给定的变量包含正常的文件路径或文件名,则返回真。
    • [ -x $var ] # 如果给定的变量名包含的文件可执行,则返回真。
    • [ -d $var ] # 如果给定的变量包含的是目录,则返回真。
    • [ -e $var ] # 如果给定的变量包含的文件存在,则返回真。
    • [ -c $var ] # 如果给定的变量包含的是一个字符设备文件的路径,则返回真。
    • [ -b $var ] # 如果给定的变量包含的是一个块设备文件的路径,则返回真。
    • [ -w $var ] # 如果给定的变量包含的文件可写,则返回真。
    • [ -r $var ] # 如果给定的变量包含的文件可读,则返回真。
    • [ -L $var ] # 如果给定的变量包含的是一个符号链接,则返回真。
    fpath="/etc/passwd"if [ -e $fpath ]; then    echo File exists;else    echo Does not exist;fi
  5. 字符串比较
    • 使用字符串比较时,最好用双中括号,因为有时候采用单个中括号会产生错误。
    • [[ $str1 = $str2 ]] :当str1等于str2时,返回真,也就是说,str1和str2包含的文本是一模一样的。
    • [[ $str1 == $str2 ]]:这是检车字符串是否相等的另一种写法。
    • [[ $str1 != $str2 ]]:如果str1和str2不相同,则返回真。
    • [[ $str1 > $str2 ]] :如果str1的字母序比str2大,则返回真。
    • [[ $str1 < $str2 ]] :如果str1的字母序比str2小,则返回真。
    • [[ -z $str1 ]] :如果str1包含的是空字符串,则返回真。
    • [[ -n $str1 ]] :如果str1包含的是非空字符串,则返回真。
    if [[ -n $str1 ]] &&[[ -z $str2 ]];    then        commands;    fi
    str1="Not empty "    str2=""    if [[ -n $str1 ]] && [[ -z $str2 ]];    then        echo str2 is nonempty and str2 is empty string.    fi

test命令可以用来执行条件检测

    if [ $var -eq 0 ]; then echo "True"; fi    # 也可以写成:    if test $var -eq 0; then echo "True"; fi
原创粉丝点击