zoukankan      html  css  js  c++  java
  • 第二章 shell的语法

    变量:字符串、数字、环境和参数

    获取变量内容可以在变量前使用$字符,使用echo指令可以将变量内容输出到终端。

    wuchao@wuchao-Lenovo:~$ var=hello
    wuchao@wuchao-Lenovo:~$ echo $var
    hello
    wuchao@wuchao-Lenovo:~$ var=2+3
    wuchao@wuchao-Lenovo:~$ echo $var
    2+3

    注意:如果字符串中间有空格,则必须使用引号。此外等式两边不能有空格。

    使用read命令可以将用户输入的值赋给变量

    wuchao@wuchao-Lenovo:~$ read var
    hello world
    wuchao@wuchao-Lenovo:~$ echo $var
    hello world

    引号的使用

    双引号中使用$var时,程序自动替换成变量的值。单引号中使用$var时,不会发生替换。如果想把$当作普通字符,则在$使用取消它的特殊含义。

    wuchao@wuchao-Lenovo:~$ var="hello world"
    wuchao@wuchao-Lenovo:~$ echo $var
    hello world
    wuchao@wuchao-Lenovo:~$ echo "$var"
    hello world
    wuchao@wuchao-Lenovo:~$ echo '$var'
    $var
    wuchao@wuchao-Lenovo:~$ echo $var
    $var

    环境变量

    $HOME :当前home目录

    $PATH :搜索命令的目录

    $0 :shell脚本的名字

    $# :传递给脚本的参数的个数

    $$ :shell脚本的进程号

    参数变量

    $1 , $2,…… :脚本程序的参数

    $* :在一个变量中列出所有参数,使用IFS环境变量作为分隔符

    $@ :$*的变体。但不使用IFS环境变量

    wuchao@wuchao-Lenovo:~/linux_program$ cat test02
    #!/bin/sh
    var=hello
    echo "value of var is: $var"
    echo "runing"
    echo "this shell name is $0"
    echo "the first param is $1"
    echo "the second param is $2"
    
    
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02 Hell World
    value of var is: hello
    runing
    this shell name is ./test02
    the first param is Hell
    the second param is World
    wuchao@wuchao-Lenovo:~/linux_program$ 

    条件:shell中的boolean值

    shell的boolean判断常常使用test或[命令。其中[命令可以使用]结尾。

    比如测试hello.h文件是否存在:

    if test -f hello.h

    then

    ...

    fi

    或者

    if [ -f hello.h ]

    then

    ...

    fi

    注意:[后面必须有空格

    test命令归为一下三类:

    字符串比较

    string1 = string2  相同为真

    string1 != string2   不同为真

    -n string1    判断字符串是否为非0,字符为空时为false

    -z string1    判断字符串是否为0,字符串为null时为true

    算术比较

    expression1 -eq expression2    表达式结果相等

    expression1 -ne expression2    表达式结果不相等

    expression1 -gt expression2     前者大于后者

    expression1 -ge expression2    前者大于等于后者

    expression1 -lt expression2      前者小于后者

    expression1 -le expression2     前者小于等于后者

    文件条件测试

    -d file    测试文件是否是一个目录

    -e file    测试文件是否存在

    -f file     测试文件是否是一个普通文件

    -g file    如果文件的set-group-id位被设置则为真

    -r file    测试文件是否可读

    -s file    测试文件大小是否不为0

    -u file    如果文件的set-user-id位被设置则为真

    -w file    测试文件是否可写

    -x file    测试文件是否可执行

    程序控制:if、elif、for、while、until、case

    if语句

    if condition

    then

    statements

    else

    statements

    fi

    elif语句

    if condition

    then

    statements

    elif

    then

    statements

    else

    statements

    fi

    for循环

    for variable in values

    do

    statements

    done

    举例:

    wuchao@wuchao-Lenovo:~/linux_program$ cat test02
    #!/bin/sh
    
    for var in  hello world cc
    do
      echo $var
    done
    
    exit 0
    
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02
    hello
    world
    cc

    使用通配符的for循环

    打印所有以foo开头并以.sh结尾的文件

    wuchao@wuchao-Lenovo:~/linux_program$ ls foo*.sh
    foo01.sh  foo02.sh  foo03.sh
    wuchao@wuchao-Lenovo:~/linux_program$ cat test02
    #!/bin/sh
    
    for var in  $(ls foo*.sh)
    do
      echo $var
    done
    
    exit 0
    
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02
    foo01.sh
    foo02.sh
    foo03.sh

    while语句

    while condition

    do

      statements

    done

    until语句

    until condition

    do

      statements

    done

    case语句

    case variable in

    pattern [ | pattern ] ...) statements;;

    pattern [ | pattern ] ...) statements;;

    ...

    esac

    注:每个模式下都可以放置多条语句,因此使用;;表示模式的结束。

    case示例一:

    wuchao@wuchao-Lenovo:~/linux_program$ cat test02
    #!/bin/sh
    echo "please input you choice (y,yes,n,no)"
    read choice;
    case "$choice" in
      y ) echo "your choice is yes";;
      yes ) echo "your choice is yes";;
      n ) echo "your choice is no";;
      no ) echo "your choice is no";;
      * ) echo "wrong input";;
    esac
    exit 0
    
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02
    please input you choice (y,yes,n,no)
    yes
    your choice is yes
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02
    please input you choice (y,yes,n,no)
    d
    wrong input

    case语句当匹配到以后,不会再继续匹配后面的模式。使用通配符*可以匹配所有情况。

    case示例二:合并匹配模式

    wuchao@wuchao-Lenovo:~/linux_program$ cat test02
    #!/bin/sh
    echo "please input you choice (y,yes,n,no)"
    read choice;
    case "$choice" in
      y|yes ) echo "your choice is yes";;
      n|no ) echo "your choice is no";;
      * ) echo "wrong input";;
    esac
    exit 0
    
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02
    please input you choice (y,yes,n,no)
    y
    your choice is yes

    case示例三:执行多条语句

    wuchao@wuchao-Lenovo:~/linux_program$ cat test02
    #!/bin/sh
    echo "please input you choice a num (0-2)"
    read choice;
    case "$choice" in
      0 ) echo "num is 0";
          echo "num is 0";;
      1 ) echo "num is 1";
          echo "num is 1";;
      2 ) echo "num is 2";
          echo "num is 2";;
      * ) echo "bad input";
          echo "bad input";;
    esac
    exit 0
    
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02
    please input you choice a num (0-2)
    1
    num is 1
    num is 1
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02
    please input you choice a num (0-2)
    3
    bad input
    bad input

    命令列表

    AND列表

    statement1 && statement2 && statement3 ……

    只有前面的命令执行成功后才执行后一条。&&用于测试前一条语句是否成功执行,成功的话执行后一句。

    OR列表

    statement1 || statement2 || statement3 ……  

    直到某一个命令执行成功才结束,即当前面的命令返回false时才执行下一条。||用于测试前一条语句是否成功执行,失败的话执行后一句。

    函数

    函数必须在调用前定义。

    函数被调用时,脚本程序的位置参数($*,$@,$#,S1,$2等)会被替换成函数的参数。执行完毕后在恢复原来的值。

    举例:

    #!/bin/sh
    
    #以下为函数
    yes_or_no(){
      echo "Is your name $* ?"
      while true
      do
        echo -n "Enter yes or no:"
        read x
        case "$x" in
          y | yes ) return 0;;
          n | no ) return 1;;
          * ) echo "Anser yes or no"
        esac
      done
    }
    
    #以下为主程序
    echo "Original params are $*"
    if yes_or_no "$1"
    then
      echo "Hi $*,nice name"
    else
      echo "Never mind"
    fi
    
    exit 0
    yes_or_no "$1"表示执行yes_or_no函数,并传递变量$1给函数

    执行结果
    wuchao@wuchao-Lenovo:~/linux_program$ ./test02 wu chao
    Original params are wu chao
    Is your name wu ?
    Enter yes or no:y
    Hi wu chao,nice name

    注意:shell中命令执行成功时返回状态码0,失败返回非0,故if遇到0时,为真。比如上面的例子。函数yes_or_no返回0时,主程序的if语句才执行then后面的语句。

    shell内置命令

    break 命令

    跳出一层循环

    : 命令

    空命令,相当于true的别名。

    continue 命令

    跳到下一次循环,继续执行。

    . 命令

    一般情况下,当脚本执行一条外部命令或脚本程序时会创建一个新的环境,命令将在新的环境下执行,结束后退回父shell。但外部的source命令和.命令(两个命令一致)在执行脚本程序中列出的命令时,使用的是调用该脚本程序的同一个shell。因此使用.命令执行程序,可以改变当前shell的环境变量,程序结束后,环境变量仍然有效。

    比如以下脚本:

    # test.sh
    echo
    “shell is runing” exit 0

    当执行./test.sh时,终端显式“shell is runing”,当执行. ./test.sh时,由于脚本最后一行exit 0是退出shell,结果当前shell被关闭。

    echo 命令

    echo默认输出带换行符的字符串。可以使用echo -n “string”来输出不换行的字符串。

    eval 命令

    对参数进行求值。(个人理解为将字符串解析成命令)

    举例:

    wuchao@wuchao-Lenovo:~/linux_program$ foo=10
    wuchao@wuchao-Lenovo:~/linux_program$ x=foo
    wuchao@wuchao-Lenovo:~/linux_program$ y='$'$x
    wuchao@wuchao-Lenovo:~/linux_program$ echo $y
    $foo
    wuchao@wuchao-Lenovo:~/linux_program$ eval y='$'$x
    wuchao@wuchao-Lenovo:~/linux_program$ echo $y
    10

    exec命令

    将当前shell替换为一个不同的程序。

    exit n 命令

    交互式shell使用该命令时会使你退出系统。

    export 命令

    将作为它参数的变量导出到子shell中,并使之生效。默认下,一个shell中被创建的变量在这个shell调用的子shell中是不可用的。export将自己的参数创建为一个环境变量,而这个环境变量是可以被当前程序调用的其他脚本和程序读取的。

    (个人理解:父进程的一般变量,子进程不能访问,而环境变量可以)

    外部命令和shell脚本执行时,会创建新的shell,内置命令好像不创建新的shell。

    expr 命令

    将它的参数当作表达式求值。

    比如:x=`expr $x + 1` 或 x=$(expr $x + 1)  (注意+左右的空格)

    反引号(``)使x的取值为expr $x + 1的执行结果。也可以用$()替换反引号。

    expr现在被$((...))替代了。

    如:x=$(($x + 1))

    printf 命令

    类似于c++的printf

    格式化字符串然后被用来解释后续参数的含义并输出结果。

     

    wuchao@:~$ printf "%s %d	%s" "Hi There" 15 people
    Hi There 15    people

     

     

    return 命令

    函数返回值

    set 命令

    为shell设置参数变量

    shift 命令

    把所有参数变量左移一个位置,使$2变成$1,$3变成$2……,$0保持不变。

     

    wuchao@:~/linux_program$ cat test02
    #!/bin/sh
    while [ "$1" != "" ];
    do
      echo "$1"
      shift
    done
    exit 0
    
    wuchao@:~/linux_program$ ./test02 aa bb cc
    aa
    bb
    cc

     

     

    trap 命令

    指定在接收到信号时将要采取的行动。

    trap command signal

    信号 说明
    HUP(1) 挂起,通常因终端掉线或用户退出而引发
    INT(2) 中断,通常因Ctrl+C组合键而引发
    QUIT(3) 退出,通常因Ctrl+组合键而引发
    ABRT(6) 中止,通常因严重的执行错误而引发
    ALRM(14) 报警,通常用来处理超时
    TERM(15) 终止,通常在系统关机时发送

     

    unset 命令

    从环境中删除变量或函数。

    find 命令

    格式:

    find [path] [options] [tests] [actions]

    选项 含义
    -depth 在查看目录本身之前先搜索目录的内容
    -follow 跟随符号链接
    -maxdepths N 最多搜索N层目录
    -mount(或-xdev) 不搜索其他文件系统的目录

    下面是测试部分,每种测试返回的结果有两种可能:true和false。find命令开始工作时,按照顺序将每种测试应用到它搜索到的每个文件,如果返回false,find停止处理当前找到的文件,并继续搜索。如果返回true,find将继续下一个测试或对当前文件采取行动(actions)。

    测试 含义
    -atime N 文件在N天前被访问过
    -mtime N 文件在N天前被修改过
    -name pattern 文件名匹配提供的模式pattern,为了确保pattern被传递给find而不是由shell处理,pattern必须被引号括起。
    -newer otherfile 文件比otherfile新
    -type c 文件的类型是c(常见的是d和f)
    -user username 文件的拥有者

    还可以使用操作符来组合测试

    操作符,短格式 操作符,长格式 含义
    -not 测试取反
    -a -and 两个测试必须为真
    -o -or 两个测试必须有一个为真

    可以使用圆括号来强制优先级。括号需要使用反斜杆。如果文件名处使用的是匹配模式,则此处必须用引号。

    如:(-newer X -o -name "_*"  )

     

    动作 含义
    -exec command 执行一条命令,后面跟一个{}用于表示当前的完整路径,然后以 ;结束。
    -ok command 同上,只不过每次询问用户。
    -print 打印文件名
    -ls 对当前文件使用ls -dils

    举例:

    在当前目录查找比bill.c文件更新的文件,并且使用ls -l命令处理这些找到的文件。

     

    wuchao@:~/linux_program$ find . -newer bill.c -type f -exec ls -l {} ;
    -rw-rw-r-- 1 wuchao wuchao 46 10月 12 19:16 ./test01.sh
    -rw-rw-r-- 1 wuchao wuchao 1528 10月 10 15:29 ./fred.o
    -rw-rw-r-- 1 wuchao wuchao 1568 10月 10 15:39 ./program.o
    -rw-rw-r-- 1 wuchao wuchao 1528 10月 10 15:29 ./bill.o
    -rwxrwxr-x 1 wuchao wuchao 8656 10月 10 15:59 ./a.out
    -rwxrwxr-x 1 wuchao wuchao 8720 10月 10 15:56 ./program
    -rw-rw-r-- 1 wuchao wuchao 86 10月 10 15:37 ./program.c
    -rw-rw-r-- 1 wuchao wuchao 0 10月 12 20:02 ./foo01.sh
    -rw-rw-r-- 1 wuchao wuchao 0 10月 12 20:02 ./foo02.sh
    -rw-rw-r-- 1 wuchao wuchao 3266 10月 10 15:54 ./libfoo.a
    -rwxrw-r-- 1 wuchao wuchao 59 10月 13 20:21 ./test02
    -rw-rw-r-- 1 wuchao wuchao 35 10月 10 15:33 ./lib.h
    -rw-rw-r-- 1 wuchao wuchao 0 10月 12 20:03 ./foo03.sh

     

     

    grep 命令

    参数:

    grep [options] pattern [files]

    选项 含义
    -c 输出匹配行的数目,而不是匹配行
    -E 启用扩展表达式
    -h 取消每个输出行的普通前缀,即匹配查询模式的文件名
    -i 忽略大小写
    -l 只列出包含匹配行的文件名,而不是匹配行
    -v 对匹配模式取反

    正则表达式

    常用的特殊字符

    字符 含义
    ^ 指向一行的开头
    $ 指向一行的结尾
    . 任意单个字符
    [] 方括号内的一个字符访问,其中任何一个字符都可以被匹配,例如字符范围a~e,或在字符范围前面加上^符号表示取反向字符范围。

     

    特殊匹配模式

     匹配模式 含义
    [:alnum:] 大小写字符及数字,0-9,A-Z,a-z
    [:alpha:] 英文大小写字符
    [:blank:] 空格键与tab键
    [:cntrl:] 控制按键,CR,LF,TAB,DEL等
    [:digit:] 代表数字
    [:graph:] 除空格符(空格和Tab)外其他按键
    [:lower:] 小写字符
    [:print:] 可以被打印出来的字符
    [:punct:] 标点字符," ' ? ; : # $
    [:upper:] 大写字符
    [:space:] 任何会产生空白的字符
    [:xdigit:] 十六进制数字

     

    基础正则表达式字符

     选项 意义
    ^word 带查找的字符串在行首
    word$ 待查找的字符串在行尾
    . 代表一定有一个任意字符的字符
    转义字符
    * 重复零到无穷多个前一个字符
    [list] 从字符集合的RE字符里找到想要选取的字符
    [n1-n2] 从字符集合的RE字符里找到想要选取的字符范围
    [^list]
    从字符集合的RE字符里找到不想要选取的字符范围
    {n,m} 前一个字符重复n到m次

    命令的执行

    捕获命令的执行结果: $(command)

    算术扩展

    $((...))

    wuchao@:~/linux_program$ cat test02
    #!/bin/sh
    x=0
    while [ "$x" -ne 10 ];do
      echo $x
      x=$(($x+1))
    done
    exit 0
    
    wuchao@:~/linux_program$ ./test02
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    wuchao@:~/linux_program$

    参数扩展

    参数扩展 说明
    ${param:-default} 若 param 未定义或为空,则返回 default,否则返回 param 的值
    ${param-string} 若 param 未定义,则返回 string,否则返回 param 的值
    ${param:+string} 若 param 为非空,则返回 string,否则返回 param 的值
    ${#param} 给出param的长度
    ${param%word} 从param的尾部开始删除与word匹配的最小部分,返回剩余部分
    ${param%%word} 从param的尾部开始删除与word匹配的最长部分,返回剩余部分
    ${param#word} 从param的头部开始删除与word匹配的最小部分,返回剩余部分
    ${param##word} 从param的头部开始删除与word匹配的最长部分,返回剩余部分

    here文档

    本章节应用程序设计

    查看程序请点击这里

  • 相关阅读:
    第60届IMO 第5题
    第31届IMO 第2题
    洛谷【P1595 信封问题】 题解
    洛谷【P2022 有趣的数】 题解
    洛谷【P5004 专心OI
    04-----jQuery的属性操作
    03-----jQuery动画效果
    02-----jQuery的选择器
    01-----jQuery介绍
    17-----案例
  • 原文地址:https://www.cnblogs.com/wuchaodzxx/p/5946368.html
Copyright © 2011-2022 走看看