zoukankan      html  css  js  c++  java
  • linux编程-bash

    1. 基本语法

    1.1 注释

    注释以"#"开始, "#"后面的内容被忽略.

    说明:

    1. "#" 前可以没有语句, 表示整行被注释.
    2. "#" 前可以有语句, 只注释"#"后面的内容.

    1.2 变量

    $ VAR_NAME='value'      # 变量赋值, 注意等号两边不能有空格
    $ echo "I am $VAR_NAME, ${VAR_NAME}" # 通过$符使用变量
    $
    $ LIST=$(ls)               # 将shell命令结果赋值给变量,
    $ SERVER_NAME=$(hastname)  # 参考子命令扩展
    

    全局变量:在脚本中任何位置都可以使用该变量,shell变量默认都是全局变量。
    本地变量:可以在函数内部声明本地变量,使用local关键字。

    1.3 数组

    数组直接赋值, 注意等号两边不能有空格.

    $ myarr=()                        # 定义一个空数组  
    $ myarr=(1 2 3 4 5)               # 数组元素都为数字  
    $ myarr=(one two three four five) # 数组元素都为字符串  
    $ myarr=(1 two 3 four 5)          # 数组元素由数字和字符串组成  
    $ myarr=(1 two 3 "a line")        # 数组元素包含空格  
    

    通过数组下标赋值

    $ myarr[0]=1         # 通过下标为数组元素赋值  
    $ myarr[2]=test  
    $ myarr[9]="a line"  # 下标超出原数组长度也可以直接赋值  
    

    获取数组信息

    $ myarr=(one two three four five) # 数组元素都为字符串
    $ 
    $ echo ${myarr[0]}          # 通过下标访问元素
    one
    $ echo ${myarr[@]}          # 打印整个数组
    one two three four five
    
    $ echo ${#myarr[*]}         # 获取数组长度
    5
    $ echo ${#myarr[@]}         # 同上
    5
     
    $ echo ${#myarr[9]}         # 获取元素的长度  
    0
    $ echo ${myarr[@]:3:2}      # 数组切片, 从第3个元素开始, 元素个数为2  
    four five  
    
    $ myarr+=(six seven)        # 给数组追加新数组  
    $ echo ${myarr[@]}  
    one two three four five six seven  
    
    $ unset ${myarr[9]}         # 删除数组某个元素  
    $ unset myarr               # 删除整个数组  
    

    通过变量做下标:

    $ myarr=(one two three four five)  
    $ i=0  
    $ echo ${myarr[i]}    # 通过变量做下标  
    one  
    $ echo ${myarr[i+1]}  # 通过变量运算做下标  
    two  
    

    遍历数组: 通过in关键字, ${myarr[@]}加双引号, 元素中有空格不会被拆分. 如果不加双引号, 最后一个元素中有空格, 会被拆分.

    $ myarr=(one two three four "a line")
    $ for ele in "${myarr[@]}"; do echo $ele ; done
    one
    two
    three
    four
    a line
    $
    

    遍历数组: 通过下标自增

    $ myarr=(one two three four "a line")
    $ for ((i=0;i<${#myarr[*]};i++)); do echo ${myarr[i]}; done
    one
    two
    three
    four
    a line
    $
    

    遍历数组: 通过下标自增2

    $ for ((i=0;i<${#myarr[*]};i+=2)); do echo "${myarr[i]}, ${myarr[i+1]}"; done  
    one, two  
    three, four  
    a line,  
    $  
    

    1.4 命令行参数

    $0 # 脚本名称
    $1 # param1
    $2 # param2
    ...
    $@ # 整个参数数组,$1 $2 ...,不包括$0。
    

    1.5 获取用户输入

    read命令接收键盘的输入

    $ read -p "Please Enter Your Name: " NAME
    Please Enter Your Name: ZhangSan
    $ echo "Your Name Is: $NAME"
    Your Name Is: ZhangSan
    

    1.6 文件测试

    注意,方括号与中间内容必须有空格。

    [ -d FILE_NAME ] # FILE_NAME是dir
    [ -e FILE_NAME ] # FILE_NAME存在
    [ -f FILE_NAME ] # FILE_NAME存在且是regular file
    [ -r FILE_NAME ] # FILE_NAME是readable
    [ -s FILE_NAME ] # FILE_NAME存在且不为空
    [ -w FILE_NAME ] # FILE_NAME有write permission
    [ -x FILE_NAME ] # FILE_NAME是excutable
    

    1.7 字符串测试

    注意,方括号与中间内容必须有空格。

    [ -z STRING ]         # STRING是空的
    [ -n STRING ]         # STRING不是空的
    [ STRING1 = STRING2 ] # 字符串相等
    [ STRING1 != STRING2 ]# 字符串不相等
    

    1.8 算术测试

    注意,方括号与中间内容必须有空格。

    [ var1 -eq var2 ] # 相等
    [ var1 -ne var2 ] # 不相等
    [ var1 -lt var2 ] # var1 less than var2
    [ var1 -le var2 ] # var1 less than or equal to var2
    [ var1 -gt var2 ] # var1 greater than var2
    [ var1 -ge var2 ] # var1 greater than or equal to var2
    

    1.9 逻辑运算 &&, ||

    逻辑与: &&
    逻辑或: ||

    例子:创建目录tempDir成功后,进入该目录并创建子目录subTempDir

    mkdir tempDir && cd tempDir && mkdir subTempDir
    

    1.10 if条件判断

    语法1: 只有一个if分支

    if [ condition-is-true ]
    then # 注意,then不能直接写在if语句行, 除非在if语句行尾加分号后再使用then
        command 1
        …
        command N
    fi
    

    语法2: if带elif分支

    if [ condition-is-true ]; then
        command 1
    elif [ condition-is-true ]; then
        command 2
    elif [ condition-is-true ]; then
        command 3
    else
        command 4
    fi
    

    1.11 case条件判断

    语法:

    case "$VAR" in
      pattern_1)
        # commands when $VAR matches pattern 1
        ;;
      pattern_2)
        # commands when $VAR matches pattern 2
        ;;
      *)
        # This will run if $VAR doesnt match any of the given patterns
        ;;
    esac
    

    例子:

    read -p “Enter the answer in Y/N: ” ANSWER
    case “$ANSWER” in
        [yY] | [yY][eE][sS])
            echo “the answer is Yes.”
            ;;
        [nN] | [nN][oO])
            echo “the answer is No.”
            ;;
        *)
            echo “invalid answer .”
            ;;
    esac
    

    1.12 for循环

    语法1:

    for VARIABLE_NAME in ITEM_1 ITEM_N
    do
      command 1
      command 2
        ...
        ...
      command N
    done
    

    例:

    $ for V in a b c; do echo $V; done
    a
    b
    c
    $ 
    $ COLORS="red green blue"
    $ for C in $COLORS; do echo $C ; done
    red
    green
    blue
    $
    
    FIELS=$(ls *txt)
    NEW="new"
    for FILE in $FILES
    do
        echo "Renaming $FILE to $NEW-$FILE"
        mv $FILE $NEW-$FILE
    done
    

    语法2:

    for (( VAR=1;VAR<N;VAR++ )) # 注意, 有两对小括号, 参考算术扩展.
    do
      command 1
      command 2
        ...
        ...
      command N
    done
    

    $ for ((I=0;I<5;I++)); do echo $I; done
    0
    1
    2
    3
    4
    

    1.13 while循环

    语法:

    while [ condition-is-true ]
    do
        command 1
        command 2
        …
        command N
    done
    

    例: 按行读取文件/ect/passwd的内容

    LINE=1
    while read CURRENT_LINE; do       # CURRENT_LINE是内置变量, 当前行的内容.
        echo "${LINE}: $CURRENT_LINE"
        ((LINE++))                    # 变量自增, 见模式扩展
    done < /etc/passwd
    

    1.14 循环控制

    continue # 结束本次循环节,进入下一个循环节
    break    # 结束整个循环
    

    1.15 函数

    语法:

    function func_name() {
        command 1
        command 2
        ...
        command N
    }
    

    例子:声明一个函数并调用

    #!/bin/bash
    function myFunc() {
        echo "Shell Scripting Is Fun!"
    }
    
    myFunc # 函数调用
    

    函数参数

    $1 第一个参数
    $2 第二个参数
    $@ 参数数组
    

    参数之间使用空格分隔

    #!/bin/bash
    function add() {
        let "SUM=$1+$2"
        return $SUM
    }
    
    A=$(add 3 4)
    echo "3+4=${A}"
    

    2. 通配符 or 模式扩展

    共有8种模式扩展,按优先级顺序分为:

    序号 名称 说明
    1 brace expansion 大括号 {}
    2 tilde expansion 波浪号 ~
    3 parameter and variable expansion 参数? 变量?
    4 arithmetic expansion 算术扩展
    5 command substitution 子命令扩展
    6 word splitting 词分割
    7 pathname/filename expansion 路径名扩展
    8 process substitution 过程替换

    2.1 brace expansion {}

    大括号扩展。

    有两种形式:

    1. pre + {str1,str2[,…,strN]} + post
    2. pre + {START..END[..INCR]} + post # 扩展成一个序列

    使用注意事项:

    1. 这是单纯对字符串的扩展,即使不存在对应的文件名,也会扩展成功。
    2. 逗号两边都不允许有空格。
    3. 大括号与中间内容之间不允许在空格。
    4. 逗号前可以为空,表示待扩展的为空字符,见后面例子。
    5. 大括号可以嵌套使用,见后面例子。
    6. 大括号可以与其它扩展联用,见后面例子。
    7. START..END用于扩展为一个序列,一般用于循环。
    8. START..END支持逆序。
    9. START..END支持添加前导字符。
    10. START..END支持指定步长: START..END..INCR。
    11. START..END可以级联使用,类似于多重循环。

    例子1: {str1,str2[,…,strN]}:

    $ echo g{o,oo,ra}d
    god good grad
    
    $ cp a.log{,.bak}     # 逗号前为空,扩展为
    cp a.log a.log.bak
    
    $ echo a{1, 2}b       # 逗号两边有空格,不作为扩展处理,当作以空格分隔的两个str。
    a{1, 2}b
    
    $ echo {j{p,pe}, pn}g # 嵌套使用大括号
    jpg jpeg png
    
    $ echo {cat, d*}      # 大括号与其它扩展联用
    cat dog door          # 注意,d*是文件名扩展,只有存在以d开头的文件名时才会扩展成功,
                          #      否则,会直接将d*当作变通str而不进行扩展。
    

    例子2: {START..END[..INCR]}:

    $ echo d{a..c}g       # 普通范围扩展
    dag dbg dcg
    
    $ echo Num{5..1}      # 逆序扩展
    Num5 Num4 Num3 Num2 Num1
    
    $ echo {08..12}       # 添加前导0,将所有结果扩展成等宽的字符串
    08 09 10 11 12
    
    $ echo {08..17..2}    # 对数字序列指定步长
    08 10 12 14 16
    
    $ echo {a..g..2}      # 对字母序列也可以指定步长
    a c e g
    
    $ echo {x..z}{0..2}
    x0 x1 x2 y0 y1 y2 z0 z1 z2
    

    2.2 tilde expansion ~

    波浪号扩展。
    主要形式如下:

    待扩展字符 扩展后字符 说明
    ~ /home/`whoami` 当前用户的主目录
    ~username /home/username 特定用户的主目录
    ~+ `pwd` 当前路径, 相当于pwd
    ~root /root /root目录

    注意:

    1. ~到/之间的字符都称为tilde-prefix。
    2. 波浪号用于匹配目录,对于~username,如果username不存在该用户,则扩展不成功。按原样输出字符。

    2.3. parameter and variable expansion

    参数和变量扩展。

    两个符号

    符号 说明
    $ 可用于参数和变量扩展,也可以用于命令替换和算术扩展。它是参数、变量、命令、算术扩展的“引导符”
    {} 在参数(参数小于10时)和变量扩展中,{}不是必须的,但它可以起到保护变量的作用,当变量名后跟着其它字符时,用于区分变量名与字符。

    注意:

    1. 使用!可以将变量的值又当作变量,多做一次扩展。
    2. 可以使用${VAR:=defaultvalue}的方式指定默认值

    例子:普通变量扩展

    $ NAME=LINUX
    $ echo pre${NAME}post # 变量扩展,将${NAME}替换为LINUX。
    preLINUXpost
    $ 
    $ echo pre$NAMEpost   # 没使用{},认为$NAMEpost是一个变量,为空,所以扩展为pre。
    pre
    

    例子:使用!

    $ NAME=LINUX
    $ LINUX=Ubuntu
    $ echo pre${NAME}post
    preLINUXpost
    $ echo pre${!NAME}post # 加一个!,将NAME的值LINUX又当作变量名,扩展为Ubuntu。
    preUbuntupost
    

    例子:自定义变量默认值

    $ NAME=      # 清空NAME的值,由于bash未定义的变量值都是空,所以直接赋值为空。
    $ echo pre{NAME:=WINDOWS}post # NAME未定义,NAME赋值为默认值WINDOWS。
    preWINDOWSpost
    
    $ echo $NAME # 在上一语句中,NAME已经被赋值为指定的默认值
    WINDOWS
    

    2.4 arithmetic expansion

    算术扩展。
    语法: $((EXPRESSION))

    注意:

    1. (())可以进行算术运算。
    2. (())可以将非10进制数转为10进制数。
    3. (())中可以有空格,也可以没空格。
    4. (())中可以使用变量。

    例子:

    $ echo $(( 3 + 4 ))
    7
    
    $ A=3
    $ echo $(($A+4))
    7
    
    $ A=$((011)); echo $A # 以0开头的是8进制数
    9
    
    $ A=$((0x11)); echo $A # 以0x开头的是16进制数
    17
    

    2.5. command substitution

    命令替换。
    语法:$(command) 或 `command`
    作用:将command的输出作为当前命令的一部分。

    注意:

    1. $(command) 使用小括号,是命令替换,${VAR}使用大括号是变量扩展。$((expr))是算术扩展。
    2. $(command) 将command的输出作为当前命令,而不只是执行command
    $ date
    2020年 08月 12日 星期三 11:06:11 CST
    
    $ $(date) # 本条命令相当于在命令行执行“2020年 08月 12日 星期三 11:06:11 CST”。
    2020年: command not found
    

    2.6 word splitting

    词分离。

    如果参数扩展、命令替换、算术扩展没有在双引号中,shell将对其结果进行“词分离”操作。

    shell把$IFS中的每一个字符看做是分隔符。
    默认情况下$IFS的值是“
    可以修改$IFS的值。

    $ IFS=’123’     # 1,2,3都作为词分隔符
    $ echo a1b2c3d4 # 在命令行中,不进行“word splitting”操作
    a1b2c3d4
    
    $ echo $(echo a1b2c3d4) # 将echo a1b2c3d4放到命令替换语句中
    a b c d4                # 以1,2,3将a1b2c3d4分割为a b c d4共4个份
    $ ls $(echo a1b2c3d4)   # 将echo a1b2c3d4放到命令替换语句中
    ls: canot access ‘a’: No such file or directory # a b c d4放到ls命令后面
    ls: canot access ‘b’: No such file or directory # 相当于执行 ls a b c d4
    ls: canot access ‘c’: No such file or directory # 
    ls: canot access ‘d4’: No such file or directory# 
    

    2.7 filename expansion

    文件名扩展.

    全为3种

    扩展名 说明
    * 匹配0~N个任意字符, 不能匹配空格 ls .txt, ls .
    ? 匹配1个任意字符,不能匹配空格 ls ?.txt
    [abc] 匹配a、b、c中任意一个字符 ls [ab].txt
    [^abc]或[!abd] 匹配a、b、c以外的任意一个字符 ls [!ab].txt
    [start-end] 匹配连续范围内的任意一个字符 ls [a-c].txt
    [^start-end] 匹配连续范围外的任意一个字符 ls [^1-3].txt

    注意:

    1. 只有对应文件名存在时才能扩展成功,否则原样输出。比如 ls *.txt如果路径下没有.txt文件,则直接将 .txt作为ls的参数,会报告没有“.txt”这个文件。
    2. *和?不能匹配空格。

    例子:

    $ ls *          # 所有文件,但不包含隐藏文件
    $ ls .*         # 所有隐藏文件,但包含了’.’和’..’这两个目录
    $ ls .[!.]*     # 所有隐藏文件,不包括’.’和’..’这两个目录
    $ ls [a-c].txt  # a.txt b.txt c.txt,只扩展为已经存在的文件。
                    #    比如如果b.txt不存在,则只扩展为a.txt c.txt
    

    2.8. process substitution

    过程替换。

    过程替换与重定向比较容易搞混:重定向是一口入一口出,过程替换是多入(实际是并没有“入”)。看如下试验:

    $ ls <(true) # 注意,”<”和”(“之间不能有空格,否则认为是重定向,语法错误。
    /dev/fd/63   # 可以认为<(true)就是文件/dev/fd/63
    
    $ vim <(ls)  # 通过vim窗口底部显示,确认文件名为/dev/fd/63.
    1 a.txt
    2 c.txt
    3 ex.sh
    
    “/dev/fd/63” [readonly] 3L, 18C
    
    $ ls <(true) >(true) # 可以认为<(LIST) 和 >(LIST)分别都是一个文件名。
    /dev/fd/62 /dev/fd/63
    
    if the “>(LIST)” form is used, writing to the file will provide input for LIST.
    if the “<(LIST)” form is used, the file passed as an argument should be read to obtain the output of LIST
    

    举例说明:

    $ cat <(ls) # <(ls)是一个文件,文件内容是ls的结果,cat这个文件。
    $ ls > >(cat) # >(cat)是一个文件,文件的内容是ls重定向来的,cat这个文件。
    

    例子:将两个文件分别sort并排序,然后找出在两个文件中都出现的行。

    $ cat a.txt
    d3
    d4
    a0
    a1
    a2
    $ cat b.txt
    c0
    c1
    c2
    d3
    d4
    
    $ comm <(sort -u a.txt) <(sort -u b.txt) # 给comm传两个文件,文件内容是sort -u结果。
    a0         #---第一列,仅出现在第一个文件中的行
    a1
    a2
        c0     #---第二列,仅出现在第二个文件中的行
        c1
        c2
            d3 #---第三列,在两个文件中都出现的行
            d4
    
  • 相关阅读:
    c++ configure帮助
    YML项目阶段性总结
    layerui 页面定位和行定位
    [转]Debian 下部署 PHP 运行环境
    win10限制访问解决
    各linux版本重启apache命令
    debian 下py2.7 安装mysql模块
    debian9 安装 odoo11 笔记用 部分内容转载前辈的,在此感谢
    在 DEBIAN 上安装 SQL SERVER
    [转帖 ]MySQL 5.7 新特性 JSON
  • 原文地址:https://www.cnblogs.com/gaiqingfeng/p/13632744.html
Copyright © 2011-2022 走看看