zoukankan      html  css  js  c++  java
  • shell语法

    1,配置文件

    登陆Linux系统,打开Terminal,使用Shell的时候,系统在背后读取了一大“坨”的配置文件,这些配置文件决定了你的Shell中的变量

    1. /etc/profile:该文件为系统的每个用户设置环境信息,当用户第一次登录系统时,该文件会被执行。 并从/etc/profile.d目录的配置文件中读取shell的设置;
    2. ~/.bash_profile或者~/.bash_login或者~/.profile:系统会依次寻找这三个文件,这些是针对当前用户的配置,但是需要注意的是,这三个文件一般不会同时存在,即使同时存在,系统按照这个顺序找到了一个以后,就不会再去读剩下的了;
    3. ~/.bashrc:该文件包含了专属于当前登录用户的bash shell的bash信息,当登录以及每次打开新的shell时,该文件都会被读取;
    4. /etc/bashrc:为每一个运行bash shell的用户执行此文件;当bash shell被打开时,该文件被读取。

    2,变量

    • 内部变量;系统定义,不能修改;
    • 环境变量;系统定义,可以修改,可以利用export将用户变量转为环境变量;
    • 用户变量;用户定义,可以定义,玩坏了都没事。

    以下这些就是内部变量:
    变量名 描述
    $# 命令行参数个数
    $0 当前程序的名称
    $? 前一个命令或函数的返回码
    $$ 当前程序的PID

    以下这些是我们常用的一些环境变量,一般我们使用env命令查看当前用户的环境变量。
    变量名 描述
    PATH 表示Shell将到哪些目录中寻找命令或程序
    SHELL 当前用户的Shell类型
    HOME 当前用户主目录
    PS1 基本提示符

    用户变量(本地变量)那就比较随性了,你可以自己随意定义,比如:
    > str='Hello World'
    > echo $str

    3,export命令

    1)export命令可以将用户变量设置为环境变量,从而可以在子Shell进程中访问该变量。
    2)我们在父Shell中输入export str以后,当我们关闭父Shell以后,该环境变量将失效,如果想打开Shell就能立刻设置export,我们可以按照我们的需要,将export str写到上面总结的那一“坨”启动配置文件中,这样就不会因为关闭了父Shell而导致export失效。
    3)我们在父Shell中输入export str以后,当我们关闭父Shell以后,该环境变量将失效,如果想打开Shell就能立刻设置export,我们可以按照我们的需要,将export str写到上面总结的那一“坨”启动配置文件中,这样就不会因为关闭了父Shell而导致export失效。
    4)你不可以在父Shell中访问子Shell中定义的变量。如果想在父Shell中访问子Shell中定义的变量,可以借助一个临时文件,将局部变量写入临时文件,父Shell读取这个文件,从而达到访问子Shell中定义的变量的目的。

    4,条件判断

    #!/bin/bash
    
    if test -f testDemo.sh
    then
        echo "testDemo.sh exists."
    fi
    
    if [ -f test.c ]
    then
        echo "test.c exists."
    else
        echo "I cannot find exists."
    fi

    if condition
    then
        statements
    elif condition
    then
        statements
    else
        statements
    fi
    
    

    字符串比较 结果
    string1 = string2 如果两个字符串相同,结果就为真
    string1 != string2 如果两个字符串不同,结果就为真
    -n string 如果字符串不为空,则结果为真
    -z string 如果字符串为一个空串(null),则结果为真

    算术比较 结果
    expression1 -eq expression2 如果两个表达式相等,则结果为真
    expression1 -ne expression2 如果两个表达式不等,则结果为真
    expression1 -gt expression2 如果expression1大于expression2,则为真
    expression1 -ge expression2 如果expression1大于等于expression2,则为真
    expression1 -lt expression2 如果expression1小于expression2,则为真
    expression1 -le expression2 如果expression1小于等于expression2,则为真
    !expression 表达式为假,则结果就为真;反之亦然

    文件条件测试 结果
    -d file 如果文件是一个目录,则为真
    -f file 如果文件是一个普通文件,则为真;也可以用来测试文件是否存在
    -r file 如果文件可读,则结果为真
    -s file 如果文件大小不为0,则结果为真
    -w file 如果文件可写,则结果为真
    -x file 如果文件可执行,则结果为真

    5,循环处理

    for foo in Jelly Think Website
    do
        echo $foo
    done
    
    echo "Enter password: "
    read pwd
    
    while [ "$pwd" != "root" ]
    do
        echo "Sorry, try again."
        read pwd
    done
    
    until condition
    do
        statements
    done

    6,分支处理

    #!/bin/bash
    
    echo "Is it morning? Please answer yes or no."
    read input
    
    case "$input" in
        yes ) echo "Good Morning.";;
        no ) echo "Good Afternoon.";;
        y ) echo "Good Morning.";;
        n ) echo "Good Afternoon.";;
        * ) echo "Sorry, answer not recognized";;
    esac
    
    exit 0

    当case语句被执行时,它会把变量input的内容与各字符串依次进行比较。一旦某个字符串与输入匹配成功,case命令就会执行紧随右括号)后面的代码,然后就结束。 在代码中,最后面的*表示匹配任何字符串,我们在写代码时,总是在其它匹配之后再添加一个*以确保如果没有字符串得到匹配,case语句也会执行某个默认动作。

    #!/bin/bash
    
    echo "Is it morning? Please answer yes or no."
    read input
    
    case "$input" in
        yes | y | Yes | YES ) echo "Good Morning.";;
        n* | N* ) echo "Good Afternoon.";;
        * ) echo "Sorry, answer not recognized.";;
    esac
    
    exit 0

    上面这段代码,使用了|符号,也就是说,也就是合并了多个匹配模式;同时还使用了*通配符;没有问题,上面的代码运行的很好。

    7,函数

    #!/bin/bash
    
    sample_text="global variable"
    
    foo()
    {
        local sample_text="local variable"
        echo "Function foo is executing..."
        echo $sample_text
    }
    
    echo "script starting..."
    echo $sample_text
    
    foo
    
    echo "script ended..."
    echo $sample_text
    
    exit 0

    返回值

    [~/shell/function]# cat return.sh 
    #!/bin/bash
    function fun1 {
      read -p "enter a: " a
      echo -n "print 2a: "
      return $[ $a * 2 ]
    }
    fun1
    echo "return value $?"
    [~/shell/function]# ./return.sh 
    enter a: 100
    print 2a: return value 200

    传递参数

    [~/shell/function]# cat ./parameter.sh 
    #!/bin/bash
    if [ $# -ne 3 ]
    then
        echo "usage: $0 a b c"
        exit
    fi
    fun3() {
        echo $[ $1 * $2 * $3 ]
    }
    result=`fun3 $1 $2 $3`
    echo the result is $result
    [~/shell/function]# ./parameter.sh  1 2 3
    the result is 6
    [~/shell/function]# ./parameter.sh  1 2
    usage: ./parameter.sh a b c

    传递参数

    #!/bin/bash
    # author:菜鸟教程
    # url:www.runoob.com
    
    funWithParam(){
        echo "第一个参数为 $1 !"
        echo "第二个参数为 $2 !"
        echo "第十个参数为 $10 !"
        echo "第十个参数为 ${10} !"
        echo "第十一个参数为 ${11} !"
        echo "参数总数有 $# 个!"
        echo "作为一个字符串输出所有参数 $* !"
    }
    funWithParam 1 2 3 4 5 6 7 8 9 34 73

    数组变量

    [~/shell/function]# cat array.sh 
    #!/bin/bash
    a=(11 12 13 14 15)
    echo ${a[*]}
    function array(){
      echo parameters : "$@" 
      local factorial=1
      for value in "$@"
      do
        factorial=$[ $factorial * $value ]
      done
      echo $factorial
    }
    array ${a[*]}
    [~/shell/function]# ./array.sh 
    11 12 13 14 15
    parameters : 11 12 13 14 15
    360360

    8,通配符

    字符 含义 实例
    * 匹配 0 或多个字符 a*b  a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如aabcb, axyzb, a012b, ab。
    ? 匹配任意一个字符 a?b  a与b之间必须也只能有一个字符, 可以是任意字符, 如aab, abb, acb, a0b。
    [list]  匹配 list 中的任意单一字符 a[xyz]b   a与b之间必须也只能有一个字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb。
    [!list]  匹配 除list 中的任意单一字符 a[!0-9]b  a与b之间必须也只能有一个字符, 但不能是阿拉伯数字, 如axb, aab, a-b。
    [c1-c2] 匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z] a[0-9]b  0与9之间必须也只能有一个字符 如a0b, a1b... a9b。
    {string1,string2,...} 匹配 sring1 或 string2 (或更多)其一字符串 a{abc,xyz,123}b    a与b之间只能是abc或xyz或123这三个字符串之一。

    [chengmo@localhost ~/shell]$ ls *.txt

    a.txt  b.txt
     
    9,元字符(meta)

    = 设定变量。
    $ 作变量或运算替换(请不要与 shell prompt 搞混了)。
    > 重导向 stdout。 *
    < 重导向 stdin。 *
    | 命令管线。 *
    & 重导向 file descriptor ,或将命令置于背境执行。 *
    ( ) 将其内的命令置于 nested subshell 执行,或用于运算或命令替换。 *
    { } 将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围。
    ; 在前一个命令结束时,而忽略其返回值,继续执行下一个命令。 *
    && 在前一个命令结束时,若返回值为 true,继续执行下一个命令。 *
    || 在前一个命令结束时,若返回值为 false,继续执行下一个命令。 *
    ! 执行 history 列表中的命令。*

    10,转义符

    有时候,我们想让 通配符,或者元字符 变成普通字符,不需要使用它。那么这里我们就需要用到转义符了。 shell提供转义符有三种。
    ‘’(单引号) 又叫硬转义,其内部所有的shell 元字符、通配符都会被关掉。注意,硬转义中不允许出现’(单引号)。
    “”(双引号) 又叫软转义,其内部只允许出现特定的shell 元字符:$用于参数代换 `用于命令代替
    (反斜杠) 又叫转义,去除其后紧跟的元字符或通配符的特殊意义。

  • 相关阅读:
    Nginx开启Gzip详解
    Nginx基础知识之————多模块(非覆盖安装、RTMP在线人数实例安装测试)
    ESA2GJK1DH1K安全篇: Android以SSL(单向认证)方式连接MQTT服务器
    ESA2GJK1DH1K安全篇: Wi-Fi 模块(8266)以SSL方式连接MQTT服务器(V0.1)
    单片机模块化程序: μCOS-II中内存管理程序使用说明
    单片机模块化程序: 数据缓存封装-内存管理实现(内存块长度充足版)
    单片机模块化程序: 数据缓存封装-环形队列实现
    单片机模块化程序: 难道有环形队列串口发送数据就万事大吉了吗
    【SpringCloud】初识springCloud
    【mybatis源码学习】mybtias扩展点
  • 原文地址:https://www.cnblogs.com/soul-stone/p/6886130.html
Copyright © 2011-2022 走看看