• shell脚本58问


    【1】交互方式、非交互方式、Shell脚本是什么?

    经常与linux打交道,肯定对shell这个词不陌生。不明白shell意思的,可以自行翻译:外壳、去壳。

    这个翻译结果怎么可以与计算机系统联系起来呢?看不懂?

    为了帮助理解shell这个词,请看下图:

    计算机系统,最内层(本质)的是硬件,然后硬件会被系统核心层包住,而在系统核心外层的就是所谓的shell,再然后shell外层的就是我们接触最多且最容易理解的应用程序。

    shell其实是一个命令解释器,作用是解释用户输入的命令和程序,命令和程序可以理解成上图中的应用程序。

    linux系统中的那些命令其实也都是一个个的小程序,只不过执行的是系统的应用功能。

    当我们在系统的终端中输入一条命令,可以立马看到一条或者几条系统回复我们的信息,其实就是shell在帮我们回复,所以shell可以称之为命令解释器。

    而这种从键盘一输入命令,就立马得到相应的回复信息,叫作交互的方式。

    了解了shell之后,再来了解下shell脚本。如果我们的命令或应用程序不在命令行直接执行,而想通过一个程序文件来执行时,这个程序文件就被称之为shell脚本。

    shell脚本里面通常内置了多条命令,有的还包含控制语句,比如if和else的条件控制语句,for的循环控制语句等。

    这些内置在一个shell脚本中的命令通常是一次性执行完成,不会不停的返回信息给用户,这种通过文件执行脚本的方式称之为非交互方式。

    shell脚本类似于windows下的批处理,但它比批处理要强大一些,现在windows下有一个叫做power shell的功能其实和linux下的shell功能媲美。

    在文本中输入一系列的命令、控制语句和变量,这一切有机的结合起来就形成了功能强大的shell脚本。

    日常工作中,经常需要使用多个命令来完成一项任务,可以添加这些所有命令在一个文本文件(Shell脚本)来统一完成这些日常工作任务。

    【2】什么是默认登录shell,如何改变指定用户的登录shell?

    登录shell是可以用户登录使用的,比如/bin/bash, /bin/sh, /bin/csh......

    一般Linux默认的用户shell都是bash,也就是你可以登录进去写命令。   

    非登录shell:经典的/bin/nologin就是一个非登录shell,也就是说如果一个用户默认的是它,这个用户即使登录进linux也无法使用linux。    

    shell是用户和计算机交流的媒介,登录shell保证用户和计算机交流,非登录shell无法让计算机和用户交流。    

    关于用户的默认登录shell是在/etc/passwd文件中记录的。本地系统示例如下:

    非登录shell有其特定的用途:比如一个用linux搭建的ftp服务器,创建了多个用户,可以将这些用户默认shell改成nologin。

    这样一来,这些用户虽然是linux上的用户却无法登录进linux主机,只能进入ftp服务器,这样也保证了安全!

    在Linux操作系统,“/bin/bash”是默认登录shell,是在创建用户时分配的。

    使用chsh命令可以改变默认的shell。示例如下所示:

    # chsh <用户名> -s <新shell>

    # chsh zhangsan -s /bin/sh

    当然,也可以直接通过修改/etc/passwd文件中对应用户的默认shell。

    查看系统中有哪些shell,利用命令:cat /etc/shells

    示例如下(本地系统中有六种shell):

    【3】可以在shell脚本中使用哪些类型的变量?

    在shell脚本,我们可以使用两种类型的变量:

    (1)系统定义变量

    (2)用户定义变量

    系统变量是由系统系统自己创建的。这些变量通常由大写字母组成,可以通过“set”命令查看。

    用户变量由系统用户来生成和定义,变量的值可以通过命令“echo $<变量名>”查看。

    shell变量的作用域可以分为三种:

    (1)有的变量只能在函数内部使用,叫做局部变量(local variable)

    (2)有的变量可以在当前shell进程中使用,叫做全局变量(global variable)

    (3)有的变量还可以在子进程中使用,叫做环境变量(environment variable)

    【4】如何将标准输出和错误输出同时重定向到同一位置?

    这个需求有两种方法可以实现:

    (1)方法一:2>&1

    示例:# ls /usr/share/doc > log.txt 2>&1

    前半部分 ls /usr/share/doc > log.txt 很容易理解,那么后面的 2>&1 是怎么回事呢?

    要解释这个问题,还得提到文件重定向。假定已经知道 > 和 < 是文件重定向符。那么1和2是什么?

    在shell中,每个进程都和三个系统文件相关联:

    (0)标准输入stdin

    (1)标准输出stdout

    (2)标准错误stderr

    三个系统文件的文件描述符分别为0、1、2。所以,这里 2>&1 的意思就是将标准错误也输出到标准输出当中。

    & 表示“等同于”的意思,2>&1,表示2的输出重定向等同于1。

    实际上,> 就相当于 1> 也就是重定向标准输出,不包括标准错误。

    而通过 2>&1 就将标准错误重定向到标准输出了(stderr已作为stdout的副本),那么再使用>重定向就会将标准输出和标准错误信息一同重定向了。

    如果只想重定向标准错误到文件中,则可以使用 2> file。

    (2)方法二:&>

    示例:# ls /usr/share/doc &> log.txt

    & 是一个描述符,如果1或2前不加&,会被当成一个普通文件。

    1>&2 把标准输出重定向到标准错误。

    2>&1 把标准错误输出重定向到标准输出。

    &> filename 把标准输出和标准错误输出都重定向到文件filename中

    摘录同问:Linux重定向中 >&2 怎么理解?

    问题补充:echo "abdefghijklmn" >&2 怎么理解?

    问题解答:>&2 即 1>&2 也就是把结果输出到和标准错误一样;之前如果有定义标准错误重定向到某log文件,那么标准输出也重定向到这个log文件。

    如:ls 2>a1 >&2 (等同 ls >a1 2>&1)

    把标准输出和标准错误都重定向到a1,终端上看不到任何输出信息。

    【5】shell脚本中“if”语法如何嵌套?

    基础语法如下:

    if [ 条件 ]
    then
       命令1
       命令2
       …
    else
       if [ 条件 ]
       then
         命令1
         命令2
         …
       else
         命令1
         命令2
         …
       fi
    fi

    if语法示例如下:

    #!/bin/bash
    a=100
    b=200
    echo "a : "$a
    echo "b : "$b
    if [ $a == $b ]
    then
        echo "a 等于 b"
    elif [ $a -gt $b ]
    then
        echo "a 大于 b"
    elif [ $a -lt $b ]
    then
        echo "a 小于 b"
    else
        echo "没有符合的条件"
    fi

    if语法输出结果:

    a : 100

    b : 200

    a 小于 b

    if嵌套语法示例如下:

    #!/bin/bash
    a=100
    b=200
    echo "a : "$a
    echo "b : "$b
    if [ $a == $b ]
    then
        echo "a 等于 b"
    else
        if [ $a -gt $b ]
        then
            echo "a 大于 b"
        else
            if [ $a -lt $b ]
            then
                echo "a 小于 b"
            else
                echo "没有符合的条件"
            fi
        fi
    fi

    if嵌套语法输出结果:

    a : 100

    b : 200

    a 小于 b

    【6】shell脚本中“$?”标记的用途是什么?

    在写一个shell脚本时,若想要检查前一命令是否执行成功,在if条件中使用“$?”可以来检查前一命令的结束状态。

    简单的例子如下:

    如果结束状态是0,说明前一个命令执行成功。

    如果结束状态不是0,说明命令执行失败。

    【7】在shell脚本中如何比较两个数字?

    在if-then中使用测试命令(-gt等)来比较两个数字。

    -gt示例如下:

    #!/bin/bash
    x=10
    y=20
    if [ $x -gt $y ]
    then
        echo "x is greater than y"
    else
        echo "y is greater than x"
    fi
    
    # 输出
    # y is greater than x

     test示例如下:

    #!/bin/bash
    num1=$[2*3]
    num2=$[1+5]
    if test $[num1] -eq $[num2]
    then
        echo '两个数字相等!'
    else
        echo '两个数字不相等!'
    fi
    
    # 输出
    # 两个数字相等!

    【8】shell脚本中break命令的作用?

    break命令一个简单的用途是退出执行中的循环。

    可以在while和until循环中使用break命令跳出循环。

    从while循环中跳出,示例如下:

    #!/bin/bash
    
    a=0
    while [ $a -lt 10 ]
    do
       echo $a
       a=`expr $a + 1`
       if [ $a -gt 8 ]
       then
           echo "break"
           break
       fi
    done
    
    # 输出
    0
    1
    2
    3
    4
    5
    6
    7
    8
    break

    从until循环中跳出,示例如下:

    #!/bin/bash
    
    a=0
    until [ ! $a -lt 10 ]
    do
       echo $a
       a=`expr $a + 1`
       if [ $a -gt 8 ]
       then
           break
       fi
    done
    
    # 输出
    0
    1
    2
    3
    4
    5
    6
    7
    8

    从 for 循环中跳出,示例如下:

    #!/bin/bash
    
    for loop in 1 2 3 4 5
    do
        echo "The value is: $loop"
        if [ $loop == 4 ]
        then
            echo "break"
            break
        fi
    done
    
    # 输出
    The value is: 1
    The value is: 2
    The value is: 3
    The value is: 4
    break

    如上三种跳出方式。

    【9】shell脚本中continue命令的作用?

    continue命令不同于break命令,它只跳出当前循环的迭代,而不是整个循环。

    continue命令很多时候是很有用的,例如错误发生,但我们依然希望继续执行大循环的时候。

    示例如下:

    #!/bin/bash
    
    for i in `seq 1 5`
    do
        echo $i
        if [ $i == 3 ]
        then
            continue
        fi
        echo $i
    done
    echo $i
    
    # 输出
    1
    1
    2
    2
    3
    4
    4
    5
    5
    5

    如上示例。

    【10】shell脚本中case语句的语法?

    基础语法如下:

    case 值 in
    模式1)
        command1
        command2
        ...
        commandN
        ;;
    模式2)
        command1
        command2
        ...
        commandN
        ;;
    esac

    case语法示例如下(用vim 新建文件cash.sh,输入内容):

    #!/bin/bash
    
    echo '输入 1 到 4 之间的数字:'
    echo '你输入的数字为:'
    read aNum
    case $aNum in
        1)  echo '你选择了 1'
        ;;
        2)  echo '你选择了 2'
        ;;
        3)  echo '你选择了 3'
        ;;
        4)  echo '你选择了 4'
        ;;
        *)  echo '你没有输入 1 到 4 之间的数字'
        ;;
    esac

    如上脚本,执行./case.sh 或 sh case.sh

    【11】shell脚本中while循环语法?

    如同for循环,while循环只要条件成立就重复它的命令块。

    不同于for循环,while循环会不断迭代,直到它的条件不为真。

    基础语法:
    while [ 条件 ]
    do
      命令…
    done

    【12】如何使脚本可执行?

    使用chmod命令来使脚本可执行。示例如下:

    # chmod a+x myshell.sh

    【13】“#!/bin/bash”的作用?

    #!/bin/bash是shell脚本的第一行,称为释伴(shebang)行。

    这里#符号叫做hash,而!叫做bang。它的意思是命令通过 /bin/bash 来执行。

    【14】shell脚本中for循环语法?

    for循环的基础语法:

    for 变量 in 循环列表
    do
      命令1
      命令2
      …
      最后命令
    done

    【15】如何调试shell脚本?

    两种方式:

    (1)使用‘-x’参数(sh -x myshell.sh)可以调试shell脚本。

    如上面例子中的case.sh脚本,调试结果如下:

    如上。

    (2)使用‘-xv’参数,但是,写法与第一种不同,具体如下:

    #!/bin/bash -xv

    应用示例如下:

    #!/bin/bash -xv
    echo '输入 1 到 4 之间的数字:'
    echo '你输入的数字为:'
    read aNum
    case $aNum in
        1)  echo '你选择了 1'
        ;;
        2)  echo '你选择了 2'
        ;;
        3)  echo '你选择了 3'
        ;;
        4)  echo '你选择了 4'
        ;;
        *)  echo '你没有输入 1 到 4 之间的数字'
        ;;
    esac

    输出结果:

    如上。

    【16】shell脚本如何比较字符串?

    test命令可以用来比较字符串。测试命令会通过比较字符串中的每一个字符来比较。

    参数         说明

    =          等于则为真

    !=         不相等则为真

    -z 字符串     字符串的长度为零则为真

    -n 字符串     字符串的长度不为零则为真

    示例如下(用vim新建test.sh文件,输入如下内容):

    #!/bin/bash
    
    num1="abcdef"
    num2="abcdefg"
    if test $num1 = $num2
    then
        echo '两个字符串相等!'
    else
        echo '两个字符串不相等!'
    fi
    
    if test $num1 != $num2
    then
        echo '两个字符串不相等!'
    else
        echo '两个字符串相等!'
    fi
    
    if test -z "$num1"
    then
        echo 'num1字符串长度为0'
    else
        echo 'num1字符串长度不为0'
    fi
    
    num2=
    if test -n "$num2"
    then
        echo 'num2字符串长度不为0'
    else
        echo 'num2字符串长度为0'
    fi
    
    # 输出
    # 两个字符串不相等!
    # 两个字符串不相等!
    # num1字符串长度不为0
    # num2字符串长度为0

    如上内容。

    【17】Bourne shell(bash) 中有哪些特殊的变量?

    下面的表列出了Bourne shell为命令行设置的特殊变量。

    内建变量    解释

    $0    当前脚本的文件名

    $n    传递给脚本或函数的参数。n是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。

    $#    传递给脚本或函数的参数个数。

    $*    传递给脚本或函数的所有参数。

    $@    传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同。可参见下文第【26】问。

    $$    当前shell进程ID。对于shell脚本,就是这些脚本所在的进程ID。

    示例如下:

    #!/bin/bash
    
    echo "0:$0"
    echo "1:$1"
    echo "2:$2"
    echo "3:$3"
    echo "4:$4"
    echo "5:$5"
    echo "6:$6"
    echo "7:$7"
    echo "8:$8"
    echo "9:$9"
    echo "#:$#"
    echo "*:$*"
    echo "@:$@"
    echo "$:$$"

    输出结果:

    如上过程。

    【18】在shell脚本中,如何测试文件?

    test命令可以用来测试文件。

    test命令基础用法如下表格:

    test 用法
    -d 文件名 如果文件存在并且是目录,返回true
    -e 文件名 如果文件存在,返回true
    -f 文件名 如果文件存在并且是普通文件,返回true
    -r 文件名 如果文件存在并可读,返回true
    -s 文件名 如果文件存在并且不为空,返回true
    -w 文件名 如果文件存在并可写,返回true
    -x 文件名 如果文件存在并可执行,返回true

    示例如下:

    #!/bin/bash
    if test -e ./shellarg.sh
    then
        echo '文件已存在!'
    else
        echo '文件不存在!'
    fi

    输出结果:

    如上。

    【19】在shell脚本中,如何写入注释?

    注释可以用来描述一个脚本可以做什么和它是如何工作的。每一行注释以#开头。

    示例如下:

    #!/bin/bash
    # This is a command

    【20】如何让shell脚本得到来自终端的输入?

    read命令可以读取来自终端(使用键盘)的数据。read命令得到用户的输入并置于你给出的变量中。

    示例如下:

    #!/bin/bash
    
    echo ‘please enter your name’
    read name
    echo “my Name is $name”

    输出结果:

    如上。

    【21】如何取消变量或取消变量赋值?

    “unset”命令用于取消变量或取消变量赋值。

    语法如下所示:

    unset [-fv] [变量或函数名称]

    -f:仅删除函数

    -v:仅删除变量

    应用示例如下:

    #!/bin/bash
    
    export JAVA_HOME=/usr/local/jdk
    echo $JAVA_HOME
    unset JAVA_HOME
    echo $JAVA_HOME
    
    a=100
    readonly PI=3.141592653
    function func() {
        echo 'call fun()'
    }
    echo 'unset a'
    unset a
    func
    echo 'unset func'
    unset func
    echo 'unset PI'
    unset PI

    输出结果:

    注意:unset 删除不了只读变量

    如上

    【22】如何执行算术运算?

    有两种方法来执行算术运算:

    1.使用expr命令

    # expr 5 + 2

    2.用一个美元符号和方括号($[ 表达式 ])

    例如:

    test=$[16 + 4]

    示例如下:

    #!/bin/bash
    
    a=2
    b=3
    result1=$[a + b]
    result2=`expr $a + $b`
    echo "result1:$result1"
    echo "result2:$result2"

     输出结果:

    如上。

    【23】在shell脚本如何定义函数呢?

    函数是拥有名字的代码块。

    当我们定义代码块,我们就可以在我们的脚本调用函数名字,该块就会被执行。示例如下所示:

    $ diskusage () { df -h ; }

    译注:下面是我给的shell函数语法,原文没有

    [ function ] 函数名 [()]

    {

    命令;

    [return int;]

    }

    示例如下:

    #!/bin/bash
    
    function demoFunc()
    {
        echo "这是我的第一个shell函数!"
    }
    echo "-----函数开始执行-----"
    demoFunc
    echo "-----函数执行完毕-----"

    输出结果:

    如上。

    【24】shell脚本中如何退出?

    利用exit退出整个脚本。

    示例如下:

    #!/bin/bash
    
    for i in `seq 1 5`
    do
        echo $i
        if [ $i == 3 ]
        then
            echo "exit"
            exit
        fi
        echo $i
    done
    echo "end"
    
    # 输出
    1
    1
    2
    2
    3
    exit

    如上示例。

    【25】shell中如何判断字符串为空?

    利用test命令,上面有讲过。

    也可以如下示例:

    #!/bin/bash
    
    string=
    
    if [ -z "$string" ]; then
        echo "string is empty"
    fi
    
    if [ -n "$string" ]; then
        echo "string is not empty"
    fi

     输出结果:

    如上

    【26】Shell脚本“$*”和“$@”的联系是什么?

    (1)相同点:都是引用所有参数。

    (2)不同点:只有在双引号中体现出来。

    假设在脚本运行时写了三个参数 1、2、3,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。

    (3)示例

    3.1 示例如下(利用vim新建脚本文件difference.sh,输出如下内容):

    #!/bin/bash
    
    echo "-- $* 演示 ---"
    for value in "$*"; do
        echo $value
    done
    
    echo "-- $@ 演示 ---"
    for value in "$@"; do
        echo $value
    done

    3.2 输出结果:

    如上

    【27】shell 如何实现定时执行任务?

    定时器可以直接利用:/bin/sleep 时间(s)

    示例如下:

    #!/bin/bash
    
    echo "timer invite"
    count=0
    while [ true ]; do
    # 定时器 1s
    /bin/sleep 1
    count=$[count + 1]
    echo "invite:$count"
    done

    输出结果:

    如上。

    【28】如何向脚本传递参数?

    不懂shell的同事,可能不会修改shell代码(比如测试的妹子)。

    那么,为了让脚本更通用,某些变量值需要在执行脚本时传入即可。

    因某种需要,想在脚本执行时传入运行过程中的需要的参数。

    示例如下(用vim新建文件argument.sh,输入如下内容):

    #!/bin/bash
    
    echo "第一个参数值:$1"
    echo "第二个参数值:$2"

    输出结果:

    如上

    【29】shell脚本如何读取文件?

    工作中,最常用的就是利用shell脚本读取文件(比如日志文件log)。

    shell脚本读取(read)文件,利用循环逐行进行读取。

    示例如下:

    #!/bin/bash
    
    echo "-------begin read file"
    while read -r line
    do 
        echo $line
    done < $1
    echo "-------end read file"

    输出结果:

    如上。注意:利用上一问的脚本传参方式将文件名作为参数传入。

    【30】如何获取一个文件每一行的第三个元素?

    使用 awk '{print $3}'

    应用示例如下:

    #!/bin/bash
    
    echo "-------begin read file content"
    while read -r line
    do 
        echo $line
    done < $1
    echo "-------end read file content"
    
    echo "---------begin read three column"
    awk '{print $3}' $1
    echo "---------end read three column"

    输出结果:

    如上。

    如何获取一个文件每一行的第三个元素 ?

    作者:IT程序狮
    链接:http://www.imooc.com/article/1131
    来源:慕课网

    【31】如何获取文件的第一行和最后一行内容?

    获取首行:head -1

    获取尾行:tail -1

    应用示例如下:

    #!/bin/bash
    
    echo "------begin read file content"
    while read -r line
    do 
        echo $line
    done < $1
    echo "------end read file content"
    
    echo "------begin read head line"
    head -1 $1
    echo "------end read head line"
    
    echo "------begin read tail line"
    tail -1 $1
    echo "------end read tail line"

    输出结果:

    如上。

    【32】假如文件中某一行的第三个元素是18,如何获取第四个元素?

    使用:awk '{ if ($3 == "18") print $4}'

    应用示例如下:

    #!/bin/bash
    
    echo "-------begin read file content"
    while read -r line
    do 
        echo $line
    done < $1
    echo "-------end read file content"
    
    echo "------begin four column value"
    awk '{ if ($3 == "18") print $4}' $1
    echo "------end four column value"

    输出结果:

    如上。

    【33】如何连接两个字符串?

    应用示例如下:

    #!/bin/bash
    
    v1="bei"
    v2="jing"
    echo "------字符串连接前"
    echo "v1:$v1"
    echo "v2:$v2"
    echo "------字符串连接方式一后"
    v3=${v1}${v2}
    echo "v3:$v3"
    echo "------字符串连接方式二后"
    echo "$v1$v2"

    输出结果:

    如上。

    【34】shell脚本中如何进行两数相加?

    方式共有六种。

    应用示例如下:

    #!/bin/bash
    
    A=5
    B=6
    echo "------原数据"
    echo "A:$A"
    echo "B:$B"
    echo "------方式一"
    let C=$A+$B
    echo $C
    echo "------方式二"
    echo $(($A+$B))
    echo "------方式三"
    echo $[$A+$B]
    echo "------方式四"
    expr $A + $B
    echo "------方式五"
    echo $A+$B | bc
    echo "------方式六"
    awk 'BEGIN{print '"$A"'+'"$B"'}'

    输出结果:

    如上。

    【35】每个脚本开始的 #!/bin/sh 或 #!/bin/bash 表示什么意思?

    这一行说明要使用的 shell。#!/bin/bash 表示脚本使用 /bin/bash。对于 python 脚本,就是 #!/usr/bin/python。

    【36】如何获取文本文件的第2行?

    使用:head -2 file | tail -1

    示例应用如下:

    #!/bin/bash
    
    echo "------begin read file content"
    while read -r line
    do 
        echo $line
    done < $1
    echo "------end read file content"
    
    echo "------begin read second line"
    head -2 $1 | tail -1
    echo "------end read second line"

    输出结果:

    如上。

    【37】bash脚本文件的第一个符号是什么?

    答:#

    【38】命令:[ -z "" ] && echo 0 || echo 1 的输出是什么?

    关于“-z” 可参考上面第15问理解:字符串长度为零则为真

    关于&& 和 ||,即分别为shell脚本的逻辑运算符AND 和 OR

    所以,[ -z "" ] 的值为真,那么:[ -z "" ] && echo 0 输出结果即为:0

    示例如下:

    #!/bin/bash
    
    echo " expression result"
    [ -z "" ] && echo 0 || echo 1
    echo "end"
    
    echo "逻辑运算符演示"
    a=10
    b=20
    
    if [[ $a -lt 100 && $b -gt 100 ]]
    then
       echo "返回 true"
    else
       echo "返回 false"
    fi
    
    if [[ $a -lt 100 || $b -gt 100 ]]
    then
       echo "返回 true"
    else
       echo "返回 false"
    fi

    输出结果:

    如上。

    【39】命令 “export” 有什么用?

    使父shell定义的变量在子shell进程中可以使用。

    用户登录到linux系统后,系统将启动一个用户shell。

    在这个shell中,可以使用shell命令或声明变量,也可以创建并运行shell脚本程序。当运行shell脚本程序时,系统将创建一个子shell。

    此时,系统中将有两个shell,一个是登录时系统启动的shell,另一个是系统为运行脚本程序创建的shell。

    当一个脚本程序运行完毕,脚本shell(即子shell)将终止,返回到执行该脚本之前的shell。

    从这种意义上来说,用户可以有许多shell,每个shell都是由某个shell(称为父shell)生的。

    在子shell中定义的变量只在该子shell内有效。

    即在一个shell脚本程序中定义了一个变量,当该脚本程序运行时,这个定义的变量只是该脚本程序内的一个局部变量,其他的shell不能引用它。

    如果要使某个变量的值可以在其他shell中被改变,可以使用export命令对已定义的变量进行输出。

    export命令将使系统在创建每一个新的shell时,定义这个变量的一个拷贝。这个过程称之为变量输出。

    (1)修改生效范围

    脚本A中export的变量在启动其他脚本时会复制一份传入其他脚本。其他脚本中对此变量的修改并不会在离开脚本后生效。

    (2)注意

    在脚本A中定义了一个变量V赋值为1,export了变量V,在脚本A中启动脚本B,在脚本B中变量V的值就是1,如果在脚本B中修改了V的值为2,那么脚本B结束后,脚本A中的V的值依然是1。

    脚本A中export的变量在启动其他脚本的时候会复制一份传入其他脚本,传入的值是调用其他脚本时的值。并不是export时的值。

    在脚本A中定义了一个变量V赋值为1,export了变量V,然后修改V为2,在脚本A中启动脚本B,在脚本B中变量V的值就是2。

    应用示例如下:

    使用vim创建脚本文件export_b.sh,输入如下内容:

    #!/bin/bash
    
    echo "exec export_b start"
    
    A="this is export_b A"
    export B="this is export_b B"
    
    ./export_a.sh
    
    echo "export_b A:$A"
    echo "export_b B:$B"
    echo "exec export_b over"

    使用vim创建脚本文件export_a.sh,输入如下内容:

    #!/bin/bash
    
    echo "exec export_a start"
    
    echo "this is export_a, A="$A""
    echo "this is export_a, B="$B""
    
    A="this is export_a A"
    B="this is export_b B"
    
    echo "exec export_a over"
    
    exit 0

    输出结果:

    如上。

    【40】如何在后台运行脚本?

    主要分为以下三种需求场景:

    (1)前台转后台运行脚本

    [1] 执行脚本backrun.sh:./backrun.sh

    [2] 中断脚本backrun.sh:ctrl+c

    [3] 在[1]的基础上将运行中的backrun.sh,切换到后台并暂停:ctrl + z

    [4] 执行ctrl + z 后,backrun.sh在后台是暂停状态(stopped)。

    使用命令:bg number让其在后台开始运行(“number”是使用jobs命令查到的[ ]中的数字,不是pid)

    (2)后台转前台运行脚本

    [1] 直接在后台运行脚本backrun.sh:./backrun.sh &

    [2] 查看当前shell环境中已启动的任务情况:jobs

    [3] 将backrun.sh切换到前台运行:fg %number(”number”为使用jobs命令查看到的[ ]中的数字,不是pid)

    [4] 中断后台运行的backrun.sh脚本:先fg %number切换到前台,再ctrl+c;或直接kill %number

    尤其注意:以上两种在后台运行backrun.sh的方法,当遇到退出当前shell终端时,后台运行的backrun.sh也就结束了。为什么呢?

    因为以上两种方法之所以使得backrun.sh在后台运行,运行backrun.sh进程的父进程是当前shell终端进程,关闭当前shell终端时,父进程退出,会发送hangup信号给所有子进程,子进程收到hangup以后也会退出。

    所以要想退出当前shell终端时backrun.sh继续运行,则有两种方式:

    方式一:使用nohup忽略hangup信号

    [1] 不中断的在后台运行backrun.sh:nohup ./backrun.sh &(backrun.sh的打印信息会输出到当前目录下的nohup.out中)

    [2] 使用jobs可看到backrun.sh处于running状态

    [3] 使用ps -ef | grep backrun.sh可查看到正在运行的backrun.sh脚本进程

    [4] 退出当前shell终端,再重新打开,使用jobs看不到正在运行的backrun.sh,但使用ps -ef可以看到

    方式二:使用setsid将其父进程改为init进程(进程号为1)

    [1] 不中断的在后台运行backrun.sh另一个命令:setsid ./backrun.sh &

    [2] 使用ps -ef | grep backrun.sh可看到backrun.sh进程的父进程id为1

    示例脚本程序如下:

    #!/bin/bash
     
    count=1
    while (( $count <= 100 ))
    do
        echo $count
        let "count++"
        sleep 1
    done

    自己运行体会。

    【41】"chmod 500 myscript.sh" 做什么?

    使脚本所有者拥有可执行权限。

    对于Linux系统中的文件来说,有三种身份和四种权限,三种身份是:

    u:文件的拥有者

    g:文件所属的群组

    o:其他用户

    对于每个身份,又有四种权限,分别为:

    r:读取文件的权限(read)

    w:写入文件的权限(write)

    x:执行的权限(execute)

    s:特殊权限

    说这么多,那500又是怎么回事呢?这其实也是Linux系统下一种表示文件权限的方式:

    在Linux系统中,对于文件的权限有读取、写入、执行三种,分别用rwx表示,另一种表示权限的方式就是使用数字,读取、写入和执行权限分别由数字4、2和1表示:

    读取权限:r 或者4

    写入权限:w 或者2

    执行权限:x 或者1

    如下图:

    那么,对于此例中的文件,用数字形式表示其权限的话,则为500,如下所示:

    如上。

    【42】">" 和 ">>" 做什么?

    重定向输出流到文件或另一个流。

    两者的区别:

    (1)> :如果文件不存在,会创建文件。如果文件存在,就将其清空。即会重写文件,如果文件里面有内容会覆盖。

    (2)>> :如果文件不存在,会创建文件。如果文件存在,将输出内容追加到目标文件中。

    示例如下(为了便于演示,只演示>>的场景。利用上问的脚本):

    #!/bin/bash
     
    count=1
    while (( $count <= 100 ))
    do
        echo $count >> backrun.log
        let "count++"
        sleep 1
    done

    输出结果:

    注意:

    因为输出重定向到日志文件backrun.log文件中,所以启动脚本后,shell端看不到输入内容。

    只能通过浏览backrun.log文件查看执行结果。

    如上。

    【43】“&”、“&&”和“;”有什么区别?

    & :希望脚本在后台运行的时候使用它

    && :当前面的脚本执行成功后,才执行后面的脚本或命令

    ;:不管前面的脚本命令执行成功与否,后面的脚本或命令继续执行

    如下三种形式:

    1.command1 & command2 & command3

    表示:三个命令同时执行

    2.command1; command2; command3

    表示:不管前面命令执行成功没有,后面的命令继续执行

    3.command1 && command2

    表示:只有前面命令执行成功,后面命令才继续执行

    利用上问的脚本command1.sh,改造如下(从1开始计数):

    #!/bin/bash
     
    count=1
    while (( $count <= 100 ))
    do
        echo $count
        let "count++"
        sleep 1
    done

    command2.sh,改造如下(从100开始计数):

    #!/bin/bash
     
    count=100
    while (( $count <= 1000 ))
    do
        echo $count
        let "count++"
        sleep 1
    done

    command3.sh,改造如下(从1000开始计数):

    #!/bin/bash
     
    count=1000
    while (( $count <= 10000 ))
    do
        echo $count
        let "count++"
        sleep 1
    done

    执行命令command4.sh,内容如下(可尝试修改三种方式运行观察):

    #!/bin/bash
    
    ./command1.sh & ./command2.sh & ./command3.sh

    自己摸索体会其差异点。

    【44】 ' 和 " 引号有什么区别?

    ' - 当我们不希望把变量转换为值的时候使用它。

    ” - 会计算所有变量的值并用值代替。

    应用示例如下:

    #!/bin/bash
    
    name=John && echo "My name is $name"
    age=18 && echo 'My age is $age'

    输出结果:

    如上。

    【45】如何只用echo命令获取字符串变量的一部分?

    应用示例如下:

    #!/bin/bash
    
    echo "----按索引截取"
    variable="My name is wangjun, and I am developer"
    echo ${variable:11:7}
    
    localpath="User:192.168.1.15:/home/wangjun"
    echo "----截取尾部方式一:"
    echo ${localpath#*:*.*.*.*:}
    echo "----截取尾部方式二:"
    echo ${localpath##*:}
    
    echo "----截取头部方式一:"
    echo ${localpath%:*.*.*.*}
    echo "----截取头部方式二:"
    echo ${localpath%%:*}
    
    echo "----截取中间字符串"
    data=`echo ${localpath#*User:}`
    ip=`echo ${data%:/home*}`
    echo "${ip}"

    输出结果:

    如上。

    【46】如何获取变量长度且获取变量最后10个字符?

    应用示例如下:

    #!/bin/bash
    
    value="abcdefghijklmnopqrstuvwxyz"
    echo "value length:${#value}"
    if [ ${#value} -gt 10 ]
    then
        echo "print tail 10:"
        echo ${value: -10}
    fi

    输出结果:

    如上。

    【47】${variable:-10} 和 ${variable: -10} 有什么区别?

    应用示例如下:

    #!/bin/bash
    
    variable=
    echo ${variable:-10}
    echo ${variable: -10}
    
    variable="abcdefghijklmn"
    echo ${variable:-10}
    echo ${variable: -10}

    输出结果:

    总结:

    ${variable:-10} :如果之前没有给 variable 赋值则输出10;如果有赋值则输出该变量。

    ${variable: -10}:输出variable的最后10个字符。

    如上。

    【48】如何只用echo命令替换字符串的一部分?

    示例如下:

    #!/bin/bash
    
    variable="abcdefghijklmn"
    echo "方式一:${variable//def/wangqi}"
    echo 方式二:${variable//def/wangqi}

    输出结果:

    如上。利用echo ${variable//pattern/replacement}进行替换操作。

    【49】如何将文本文件中的小写字符转换为大写?

    tr [:lower:] [:upper:]

    应用示例如下:

    #!/bin/bash
    
    cat $1 | tr [:lower:] [:upper:]

    输出结果:

    如上。

    【50】如何列出第二个字母是a 或 b的文件?

    ls -d ?[ab]*

    应用示例,输出结果:

    如上。

    【51】如何去除字符串中的所有空格?

    echo $string | tr -d " "

    应用示例如下:

    #!/bin/bash
    
    var="I am wang qi and my age is 18."
    echo "var:$var"
    echo $var | tr -d " "

    输出结果:

    如上。

    【52】重写这个命令,将输出变量转换为复数: item="car"; echo "I like $item" ?

    重写脚本如下:

    #!/bin/bash
    
    item="car"
    echo "I like ${item}s"

    输出结果:

    如上。

    【53】写出输出数字 0 到 20 中 3 的倍数(0 3 6 9 …)的命令?

    脚本如下:

    #!/bin/bash
    
    echo "方式一:"
    for i in {0..20..3}; do
    echo $i
    done
    
    
    echo "方式二:"
    for (( i=0; i<20; i=i+3)); do 
    echo "Welcome $i times"
    done

    输出结果:

    如上。

    【54】[ $a == $b ] 和 [ $a -eq $b ] 有什么区别?

    [ $a == $b ]  - 用于字符串比较
    [ $a -eq $b ] - 用于数字比较

    【55】[[ $string == abc* ]] 和 [[ $string == "abc" ]] 有什么区别?

    [[ $string == abc* ]]  - 检查字符串是否以字母 abc 开头

    [[ $string == "abc" ]]  - 检查字符串是否完全等于 abc

    应用示例如下:

    #!/bin/bash
    
    string="abcdefhigk"
    if [[ $string == abc* ]] ;
    then
        echo "string is start with abc"
    else
        echo "string is not start with abc"
    fi
    
    if [[ $string == "abc" ]] ;
    then
        echo "string is abc"
    else
        echo "string is not abc"
    fi

    输出结果:

    如上。

    【56】如何打印数组中的所有元素?

    应用示例如下:

    #!/bin/bash
    
    array=("Hi" "my" "name" "is")
    
    echo "打印数组第一个元素"
    echo ${array[0]}
    
    echo "打印数组的所有元素"
    echo ${array[@]}
    
    echo "输出所有数组索引"
    echo ${!array[@]}
    
    echo "移除数组中索引为2的元素"
    unset array[2]
    echo ${array[@]}
    
    echo "在数组中添加id为110的元素"
    array[110]="new_element_110"
    
    echo ${array[@]}

    输出结果:

    如上。

    【57】不用 wc 命令如何计算字符串中的单词数目?

    应用示例如下:

    #!/bin/bash
    
    string="my name is wang qi and my age is 18"
    
    echo $string
    set ${string}
    echo count:$#

    输出结果:

    如上。

    【58】shell脚本如何进行数据库操作?

    以mysql数据库为例。不用在mysql的提示符下运行mysql,在shell脚本中操作mysql的方法:

    mysql -hhostname -Pport -uusername -ppassword -e 执行的sql语句

    应用示例如下:

    #!/bin/bash
    
    HOSTNAME="119.254.95.194"
    PORT="3306"
    USERNAME="root"
    PASSWORD="123456"
    
    use_sql="use billing;"
    mysql -h${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${use_sql}"
    
    select_sql="use billing; select * from cfg_dict into outfile '/var/lib/mysql/cfg_dict.csv' fields terminated by ',';"
    mysql -h${HOSTNAME} -P${PORT} -u${USERNAME} -p${PASSWORD} -e "${select_sql}"

    如上。

    【59】待续....

    Good Good Study, Day Day Up.

    顺序 选择 循环 总结

  • 相关阅读:
    Unity5 GI与PBS渲染从用法到着色代码
    Unity场景渲染相关实现的猜想
    Ogre2.1 Hlms与渲染流程
    Ogre2.1 灯光与阴影
    Ogre2.1 结合OpenGL3+高效渲染
    Ogre2.0 全新功能打造新3D引擎
    Ogre 编辑器三(自动生成与更新Ogre对象编辑界面)
    Ogre 编辑器二(用Ogre的地形组件加载天龙八部地形)
    一个简单的旋转控制器与固定屏幕位置
    sql 触发器里,发生错误,回滚提示错误语句
  • 原文地址:https://www.cnblogs.com/Braveliu/p/11013967.html
Copyright © 2020-2023  润新知