Linux基础

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

2018-10-22  本文已影响5人  千幻流光

本文为转载
作者:数据分析之路
来源:CSDN
原文:https://blog.csdn.net/qixizhuang/article/details/77918786


函数和参数

  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炸弹::(){ :|:& };:

fork炸弹(fork bomb)在计算机领域中是一种利用系统调用fork(或其他等效的方式)进行的拒绝服务攻击。
与病毒与蠕虫不同的是,fork炸弹没有传染性。
fork炸弹会使对同时执行进程、程序数设限的系统无法执行新程序,对于不设限的系统则使之停止响应。
fork炸弹通过进程递归式派生(fork,亦即自我复制),以使系统拒绝服务甚至崩溃。

由Jaromil所作的在类UNIX系统的shell环境下触发fork炸弹的shell脚本代码,总共只用了13个字符(包括空格)
:(){ :|:& };:
注解如下:

  1. :() # 定义函数,函数名为":",即每当输入":"时就会自动调用{}内代码
  2. { # ":"函数的开始标识
  3. : # 用递归方式调用":"函数本身
  4. | # 并用管道(pipe)将其输出引至...
  5. : # 另一次递归调用的":"函数
    综合3-5,:|:表示的即是每次调用函数":"的时候就会生成两份拷贝
  6. & # 调用间脱钩,以使最初的":"函数被杀死后为其所调用的两个":"函数还能继续执行
  7. } # ":"函数的结束标识
  8. ; # ":"函数定义结束后,将要进行的操作...
  9. : # 调用":"函数,"引爆"fork炸弹
    其中函数名“:”只是简化的一例,实际实现时可以随意设定,一个较易理解(将函数名替换为“forkbomb”)的版本如下:
    forkbomb(){ forkbomb|forkbomb &} ; forkbomb
  1. 导出函数
    函数也能像环境变量一样用export导出,如此一来,函数的作用域就可以扩展到子进程中,如:$ export -f fname
  2. 读取命令返回值,如果命令成功退出则返回状态为0,否则为非0:
    $ cmd; echo $?;
  3. 向命令传递参数。假设-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. 另一种被称为反引用backtick(也有人称反标记)的方法也可以用于存储命令输出:
    $ 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
    如下图,有无双引号的类似命令,输出了不同结果:
    图1

不使用回车键来读取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  
    do 
        $@ && return
    done 
    } 

大多数现代系统中,true是作为/bin中的一个二进制文件来实现的,因此每执行一次while循环,shell就会生成一个进程。不想这样的话,可以使用shell内建的:命令

    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提供了多种类型的循环。

1. for循环

for循环的一般用法

    for var in list;   #list可以是一个字符串,也可以是一个序列。
    do
        commands;
    done

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

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

2. while循环

    while condition
    do
        commands;
    done

3. until循环

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

比较与测试

if条件判断的几种实现方式:

    if condition;
    then
        commands;
    else if condition; then
        commands;
    else
        commands;
    fi

算数比较

  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
上一篇下一篇

猜你喜欢

热点阅读