• 【shell】 1、bash语法超详细介绍


    在这里插入图片描述

    bash manual

    修改前缀

    参考

    export PS1="bash> "
    
    • 1

    路径

    dirname

    strip last component from file name

    dir=$(dirname "$0")
    
    EXAMPLES
           dirname /usr/bin/
                  -> "/usr"
    
           dirname dir1/str dir2/str
                  -> "dir1" followed by "dir2"
    
           dirname stdio.h
                  -> "."
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    set

    运行 bash script.sh 后会创建一个子 shell,可通过 set 命令对子 shell 的运行环境参数做查看和写入。其中可定制的参数有很多,详见 gnu shell manual

    • 直接执行 set 会显示已设置的环境变量 和 shell 函数
    • set -e:只要出错(即返回非 0 值)就停止运行
    • set -o pipefail:set -e 对于含有管道的命令无效,加上个参数后,管道中任意命令出错都停止运行。
      • $? (表示上一次执行结果)非 0 则表示错误,如果希望忽略某些错误则可通过 || echo 强行输出返回值为 0
    • set -u:遇到未定义变量或方法时,停止运行
    • set -x:执行每条命令前,输出命令原文

    常用函数

    ts=$(date +%s) # 获取日期,如1682072409
    echo 'a:b' | cut -d ':' -f 2 # 截取第二项(下标从0开始)
    tag=$(cat a.txt) # 命令的结果需要用"${}"包围
    uri=www."${tag}".com # 字符串拼接时,需要用$包裹变量
    
    • 1
    • 2
    • 3
    • 4

    参数

    $0 表示文件名
    $1 表示第一个参数
    if ["x$1" == "x"] 语句是一个等式检查,查看 “x$1”(即变量$1前面加上一个x)是否等于 “x”。如果等于,说明变量$1是空的。

    使用 “x$1” 的原因是为了防止某些特殊情况造成的问题。例如,当 $1 的值为一个开头为 “-” 的字符串时(例如 “-n”),如果不加 “x”,表达式会变成 "-n" == "",这可能会被shell解析为一个命令选项,而不是字符串比较,从而导致错误。

    所以,["x$1" == "x"] 语句的含义就是检查变量$1是否为空,而且这种方式可以避免某些特殊情况下的错误。

    变量

    local

    在shell脚本中,local是一种内建命令,用于在函数内部声明局部变量。这意味着这个变量的作用范围仅限于声明它的函数,一旦离开了该函数,这个变量就不再存在。

    如果在函数内部没有使用local声明变量,那么这个变量就是全局的,可以在整个脚本中访问。

    例如,考虑以下脚本:

    #!/bin/bash
    
    function test_local() {
        local local_var="I'm local"
        global_var="I'm global"
        echo $local_var
        echo $global_var
    }
    
    test_local
    echo $local_var
    echo $global_var
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    运行这个脚本的输出将是:

    I'm local
    I'm global
    <空行>
    I'm global
    
    • 1
    • 2
    • 3
    • 4

    可以看到,local_var 在函数外部是不可见的,而 global_var 在整个脚本中都是可见的

    返回值

    • if [ -z $plugin ]; then 字符串是否为0’

    正则

    LeetCode193 bash题

    打印第 n 行

    grep -n "" file.txt | grep -w '10' | cut -d: -f2
    sed -n '10p' file.txt
    awk '{if(NR==10){print $0}}' file.txt
    tail -n +10 file.txt | head -1
    
    • 1
    • 2
    • 3
    • 4

    获取行号

    row_num=$(cat file.txt | wc -l)
    echo $row_num
    if [ $row_num -lt 10 ];then
        echo "The number of row is less than 10"
    else
        awk '{if(NR==10){print $0}}' file.txt
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    核对数据库各表数量

    # input_table.list
    table1
    table2
    table3
    table4
    table5
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    #!/bin/bash
    start=$(date -j -f "%Y-%m-%dT%H:%M:%S" "2022-02-21T00:00:00" "+%s")
    end=$(date -j -f "%Y-%m-%dT%H:%M:%S" "2022-02-22T00:00:00" "+%s")
    start=$(bc -e "$start*1000")
    end=$(bc -e "$end*1000")
    for i in $(cat input_table.list); do
        echo "$i"
        psql -h192.168.2.163 -p5432 -Upostgres -ddeepface_data -c "select count(1) from $i where ts >= $start and ts < $end"
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    jq

    查询

    {
        "FOO": {
            "name": "Donald",
            "location": "Stockholm"
        },
        "BAR": {
            "name": "Walt",
            "location": "Stockholm"
        },
        "BAZ": {
            "name": "Jack",
            "location": "Whereever"
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    # cat mytxt | jq .[] | jq ."name"
    "Jack"
    "Walt"
    "Donald"
    
    # jq '.[] | select(.location=="Stockholm")' mytxt
    {
      "name": "Donald",
      "location": "Stockholm"
    }
    {
      "name": "Walt",
      "location": "Stockholm"
    }
    
    # jq -r .FOO.name mytxt   # 查 json 某 key 对应的 value
    Donald
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    检查日志

    #!/bin/bash
    # 过滤出.level = error, 但不含某些错误的日志
    jq 'select(.level=="error")|select(.msg!="pq: no partition of relation found for row")|select(.msg!="json: cannot unmarshal object into Go struct field")' /logs/myprocess.err
    
    • 1
    • 2
    • 3

    sshpass

    #!/bin/bash
    set -x
    app='a.txt b.json'
    nodes=$(cat node.list)
    password="qqq"
    cd PKG
    for i in $nodes; do
        ip=$(echo $i| cut -d':' -f1)
        port=$(echo $i| cut -d':' -f2)
        sshpass -p "$password" scp -o StrictHostKeyChecking=no -P $port $app root@$ip:~/data
    done
    cd -
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    expect

    expect 可以非交互式输入命令,设置如下 /Users/y/login.exp,然后 /Users/y/login.exp myname 192.168.2.99 mypass 即可ssh不需输入密-码,并且sudo -i不需输入密-码,简化操作。

    ➜  Desktop cat /Users/y/login.exp
    #!/usr/bin/expect
    
    set timeout 3
    spawn ssh [lindex $argv 0]@[lindex $argv 1]
    expect {
            "(yes/no)?"
            {send "yes\n";exp_continue}
            "password:"
            {send "[lindex $argv 2]\n";exp_continue}
            "from"
            {send "sudo -i\n";}
            {send "sudo -i\n";exp_continue}
            "password:"
            {send "[lindex $argv 2]\n";}
    }
    interact
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    数组

    参考

    xargs

    xargs 命令中,{} 是一个占位符,它表示 xargs 应该在哪里插入输入的参数。在使用 xargs 时,你可以用 -I 选项指定一个替代字符串,然后在命令行中的任何位置使用这个字符串,xargs 就会把这个字符串替换为从输入中读取的每个参数。

    例如,以下命令:

    echo '1 2 3' | xargs -I {} echo "Number: {}"
    
    • 1

    会输出:

    Number: 1
    Number: 2
    Number: 3
    
    • 1
    • 2
    • 3

    如果你在同一条命令中使用了两个 {}xargs 会把它们都替换为相同的参数。例如,以下命令:

    echo '1 2 3' | xargs -I {} echo "Number: {} and again: {}"
    
    • 1

    会输出:

    Number: 1 and again: 1
    Number: 2 and again: 2
    Number: 3 and again: 3
    
    • 1
    • 2
    • 3

    在这个例子中,每一行都包含两个 {}xargs 会把它们都替换为相同的参数。

    示例:批量删除 docker container

    docker ps | grep unload | awk '{print $11}' | xargs -I {} docker rm -f {}
    1. `docker ps`:列出所有运行中的 Docker 容器。
    2. `grep unload`:从上述列表中找出含有 "unload" 的行。
    3. `awk '{print $1}'`:从找到的行中提取出第一个字段(默认情况下,这是容器的 ID)。
    4. `xargs -I {} docker rm -f {}`:对每一个找到的容器 ID,执行 `docker rm -f` 命令来强制移除容器。
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    浅谈c/c++中main(),int main(),void main(),int main(void)四者之间的区别
    网络安全(黑客)自学
    2023年【安全生产监管人员】考试报名及安全生产监管人员复审考试
    【Python】【Flask】flask_login的初始化
    2023_Spark_实验十二:Spark高级算子使用
    UML 的概述 和 顺序图
    JUC学习笔记——并发工具线程池
    代码随想录算法训练营第三天| 203.移除链表元素、707.设计链表 、206.反转链表(JS写法)
    【算法】蓝桥杯全攻略:从语言基础到数学算法,一站式解锁竞赛技巧
    STM32的HAL库及其使用
  • 原文地址:https://blog.csdn.net/jiaoyangwm/article/details/126513555