• 【Shell脚本入门】


    Shell中的特殊符号

    1.$
    美元符号,用来表示变量的值。
    如变量NAME的值为Mike,则使用$NAME就可以得到“Mike”这个值。
    
    2.#
    井号,除了做为超级用户的提示符之外,还可以在脚本中做为注释的开头字母,每一行语句中,从#号开始的部分就不执行了。
    
    3.“”
    双引号,shell不会将一对双引号之间的文本中的大多数特殊字符进行解释。
    如#不再是注释的开头,它只表示一个井号“#”。但$仍然保持特殊含义。
    双引号对于某些特殊符号是不起作用的, 例如:”,$,\,`(反引号)
    双引号和单引号不能嵌套。即:echo ‘””’ 输出””, echo “’’” 输出’’
    
    4.‘’
    单引号,shell不会将一对单引号之间的任何字符做特殊解释。
    
    5.``
    倒引号,命令替换。在倒引号内部的shell命令首先被执行,其结果输出代替用倒引号括起来的文本,不过特殊字符会被shell解释。
    
    6.\
    斜杠,用来去掉在shell解释中字符的特殊含义。在文本中,跟在\后面的一个字符不会被shell特殊解释,但其余的不受影响。
    
    7.{}
    大括号,主要是和$符号配合,作为字符串连接来使用
    
    echo ${HOME}ismydir
    /home/qzkismydir
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    shell中的表达式

    1.shell 输出/输入重定向
    命令                                        说明
    command > file                            将输出重定向到 file。
    command < file                            将输入重定向到file。
    command >> file                           将输出以追加的方式重定向到 file。
    n >file                                   将文件描述符为n的文件重定向到file。
    n>> file                                  将文件描述符为n的文件以追加的方式重定向到file。
    n>&m                                      将输出文件m和n合并
    n<&m                                      将输出文件m和n合并
    << tag                                    将开始标记tag 和结束标记tag 之间的内容作为输入。
    
    输出 >
    将右尖括号前的命令的输入重定向到尖括号后的文件中。
    
    ls *.sh > list.txt
    将当前目录下所有末尾名为sh的文件的列表写入到list.txt
    
    如果要将新内容添加在文件末尾,请使用>>操作符。
    
    输入 <
    将左箭头后面的文件作为左箭头前的命令的输入。
    
    grep “a” < test.sh
    将test.sh中找到所有包含a的行
    
    command < infile > outfile
    同时替换输入和输出,执行command,从文件infile读取内容,然后将输出写入到outfile中。
    错误输出重定向
    默认bash有3个标准输入输出设备。
    
    0 标准输入
    1 标准输出
    2 错误输出
    如果执行脚本的时候发生错误,会输出到2上。
    要想就将错误的输出也输出在标准输出上,需要重定向。
    
    ./test.sh > a.log 2>&1
    后面2>&1就是将标准错误的输出重定向到标准输出上。
    
    3.tee
    将此命令的输入分叉,一支输出到屏幕一支可以重定向到其他位置。
    
    ./test.sh | tee >a.txt 2>&1
    运行test.sh,通过tee输出到a.txt,同时屏幕上可以看到输出。并且将错误输出重定向到标准输出( 2>&1 )
    
    3.exec
    将此命令后的参数作为命令在当前的shell中执行,当前的shell或者脚本不在执行。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    脚本格式

    脚本以#!/bin/bash 开头(指定解析器

    Shell中的变量

    1.常用系统变量

    $HOME、$PWD、$SHELL、$USER等
    
    echo $USER
    xinghe
    
    • 1
    • 2
    • 3
    • 4

    2.自定义变量
    1、基本语法
    (1)定义变量:变量=值
    (2)撤销变量:unset 变量
    (3)声明静态变量:readonly 变量,注意:不能 unset
    2、变量定义规则
    (1)变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
    (2)等号两侧不能有空格
    (3)在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算。
    (4)变量的值如果有空格,需要使用双引号或单引号括起来。

    (1)定义变量 A
    $ A=5
    $ echo $A 
    5
    (2)给变量 A 重新赋值 
    $ A=8
    $ echo $A 
    8
    (3)撤销变量 A
    unset A 
    $ echo $A
    
    (4)声明静态的变量 B=2,不能 unset
    $ readonly B=2 
    $ echo $B
    2
    $ B=9 
    -bash: B: readonly variable
    (5)在 bash 中,变量默认类型都是字符串类型,无法直接进行数值运算      
    $ C=1+2 
    $ echo $C 
    1+2
    (6)变量的值如果有空格,需要使用双引号或单引号括起来
    $ D=hello world
    -bash: world: command not found
    $ D="hello world"
    $ echo $D 
    hello world
    (7)可把变量提升为全局环境变量,可供其他 Shell 程序使用 export 变量名。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    3.特殊变量

    $n、$#、$*、$@、$?
    $n (功能描述:n 为数字,$0 代表该脚本名称,$1-$9 代表第一到第九个参数,十以上的参数需要用大括号包含,如${10})
    
    $# (功能描述:获取所有输入参数个数,常用于循环)。
    
    $* (功能描述:这个变量代表命令行中所有的参数,$*把所有的参数看成一个整体(一个字符串))
    $@ (功能描述:这个变量也代表命令行中所有的参数,不过$@把每个参数区分对待)
    
    $? (功能描述:最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。)**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4、Shell 数组
    数组中可以存放多个值。Bash Shell 只支持一维数组(不支持多维数组),初始化时不需要定义数组大小,数组元素的下标由 0 开始。

    Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下:

    array_name=(value1 value2 ... valuen)
    
    • 1

    也可以使用下标来定义数组:

    array_name[0]=value0 array_name[1]=value1 array_name[2]=value2
    
    • 1

    读取数组
    读取数组元素值的一般格式是:

    ${array_name[index]}
    
    • 1

    获取数组中的所有元素
    使用@ 或 * 可以获取数组中的所有元素

    ${array_name[*]} 
    ${array_name[@]}
    
    • 1
    • 2

    获取数组的长度
    获取数组长度的方法与获取字符串长度的方法相同,例如:

    #!/bin/bash 
    my_array[0]=A 
    my_array[1]=B 
    my_array[2]=C 
    my_array[3]=D  
    echo "数组元素个数为: ${#my_array[*]}" 
    echo "数组元素个数为: ${#my_array[@]}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    执行脚本,输出结果如下所示:

    $ chmod +x test.sh  
    $ ./test.sh 
    数组元素个数为: 4 
    数组元素个数为: 4
    
    • 1
    • 2
    • 3
    • 4

    运算符

    1.基本语法
    (1)expr + , - , * , / , % 加,减,乘,除,取余
    (2)“ ( ( 运算式 ) ) ”或“ ((运算式))”或“ ((运算式))[运算式]”
    注意:expr 运算符间要有空格

    (1)计算 3+2 的值
    expr 2 + 3 
    5
    (2)计算(2+3)X4 的值
    (a)expr 一步完成计算
    expr `expr 2 + 3` \* 4
    20      
    (b)采用$[运算式]方式 
    res=$((2+3))
    res=$[((2+3)*4)]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    条件判断

    1.基本语法

    [ condition ](注意 condition 前后要有空格)
    
    • 1

    注意:条件非空即为 true,[ qiuzhi ]返回 true,[] 返回 false。
    2.常用判断条件
    (1)两个整数之间比较
    = 字符串比较

    -lt 小于(less than)
    -le 小于等于(less equal) 
    -gt 大于(greater than)
    -ne 不等于(Not equal)
    -eq 等于(equal)
    -ge 大于等于(greater equal)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    (2)按照文件权限进行判断

    -r 有读的权限(read)
    -x 有执行的权限(execute)
    -w 有写的权限(write)
    
    • 1
    • 2
    • 3

    (3)按照文件类型进行判断

    -f 文件存在并且是一个常规的文件(file)
    -e 文件存在(existence) 
    -d 文件存在并是一个目录(directory)
    
    (1)23 是否大于等于 22 
    [ 23 -ge 22 ]
    echo $?
    0
    (2)helloworld.sh 是否具有写权限
    [ -w helloworld.sh ] 
    echo $?
    0
    (3)/home/atguigu/cls.txt 目录中的文件是否存在 
    [ -e /home/qiuzhi/cls.txt ]
    echo $?
    1
    (4)多条件判断(&& 表示前一条命令执行成功时,才执行后一条命令,|| 表示上一条命令执行失 败后,才执行下一条命令)
    [ -w helloworld.sh ] && echo OK || echo notok
    OK
    [ -w helloworld1.sh ] && [ ] || echo notok 
    notok
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    流程控制

    1.if 判断

    基本语法
    
    if [条件判断式] 
    then
      程序 
    fi
    或者
    if [条件判断式]
    then 
        程序
    elif [ 条件判断式 ] 
    then 
        程序
    else 
        程序
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    注意事项:
    (1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
    (2)if 后要有空格

    2.case 语句

    基本语法
    
    case $变量名 in
    "值 1")
        如果变量的值等于值 1,则执行程序 1 
    ;;
    "值 2")
        如果变量的值等于值 2,则执行程序 2 
    ;;
    ...省略其他分支... 
    *)
        如果变量的值都不是以上的值,则执行此程序
    ;; 
    esac
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    注意事项:

    case 行尾必须为单词“in”,每一个模式匹配必须以右括号“)”结束。
    双分号“;;”表示命令序列结束,相当于 java 中的 break。
    最后的“*)”表示默认模式,相当于 java 中的 default,*不可以加双引号。

    3.for 循环

    基本语法 1
    
    for ((初始值;循环控制条件;变量变化))
    do 
        程序
    done
    基本语法 2
    
    for 变量 in 值 1 值 2 值 3...
    do 
        程序
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    比较 ∗ 和 *和 @区别
    (a) ∗ 和 *和 @都表示传递给函数或脚本的所有参数,不被双引号“”包含时,都以$1 2 … 2 … 2n 的形式输出所有参数。
    (b)当它们被双引号“”包含时,“$*”会将所有的参数作为一个整体,以“$1 2 … 2 … 2n”的形式输出所有参数;“$@”会将各个参数分开,以“$1” “ 2 ” … ” 2”…” 2”n” 的形式输出所有参数。

    4.while 循环

    基本语法
    
    while [ 条件判断式 ] 
    do
        程序 
    done
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意事项:
    while 后面需要有空格

    read 读取控制台输入

    基本语法
    read(选项)(参数)
    选项:
    
    -p:指定读取值时的提示符;
    -t:指定读取值时等待的时间(秒)。
    
    参数
    
    变量:指定读取值的变量名
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    函数

    1.系统函数
    1、basename 基本语法
    basename [string / pathname] [suffix]
    basename 命令会删掉所有的前缀包括最后一个(‘/’)字符,然后将字符串显示出来。
    选项:
    suffix 为后缀,如果 suffix 被指定确定的后缀值了,basename 会将 pathname 或 string 中的后缀去掉。
    
    2、dirname 基本语法
    
    dirname 文件绝对路径
    从给定的包含绝对路径的文件名中去除文件名 (非目录的部分),然后返回剩下的路径(目录的部分)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    自定义函数

    基本语法
    [ function ] funname[()] 
    {
        Action;
        [return int;] 
    }
    funname
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    经验技巧
    (1)必须在调用函数地方之前,先声明函数,shell 脚本是逐行运行。不会像其它语言一 样先编译。
    (2)函数返回值,只能通过$?(代表了上个命令的退出状态,或函数的返回值)系统变量获得,可以显示加 return 返回,如果不加,将以最后一条命令运行结果,作为返回值。

    Shell 工具

    1.cut
    cut 的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。

    基本用法
    
    cut [选项参数] filename
    
    • 1
    • 2
    • 3

    说明:默认分隔符是制表符
    选项参数说明

    • -f: 列号,提取第几列
    • -d: 分隔符,按照指定分隔符分割列
    • -c: 指定具体的字符
    [admin@ datas]$ vim words 
    hello world !!
    hadoop spark hive
    张三 李四 王五
    (1)根据" "切割 words 第一、三列 
    [admin@ datas]$ cut -d " " -f 1,3 words
    (2)根据" "切割,获取 words 第 2 行第 1 列
    [admin@ datas]$ cat words | head -n 2 | tail -n 1 | cut -d " " -f 1
    (3)选取系统 PATH 变量值 
    [admin@ datas]$ echo $PATH
    选取系统 PATH 变量值,第 2 个“:”开始后的所有路径: 
    [admin@ datas]$ echo $PATH | cut -d : -f 2-
    选取系统 PATH 变量值,第 4 列(包括第 4 列)之前的所有路径: 
    [admin@ datas]$ echo $PATH | cut -d : -f -4
    选取系统 PATH 变量值,第 2 到 4 列(包括第 2 到 4 列)之间的所有路径: 
    [admin@mc datas]$ echo $PATH | cut -d : -f 2-4
    (4)切割 ifconfig 后打印的 IP 地址
    [admin@ ~]$ ifconfig
    获取 ip 地址
    [admin@ ~]$ ifconfig | grep "inet" | tail -n 1 | cut -d " " -f 9- | cut -d " " -f 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2.sed
    sed 是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用 sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变, 除非你使用重定向存储输出。

    基本用法
    
    sed [选项参数] ‘command’ filename
    选项参数说明
    
    -e: 直接在指令列模式上进行 sed 的动作编辑
    -i: 直接编辑文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    命令功能描述

    • a: 新增,a 的后面可以接字串,在下一行出现
    • d: 删除
    • s: 查找并替换
    (0)数据准备
    [admin@ datas]$ vim words 
    hello world !!
    hadoop spark hive
    张三 李四 王五
    (1)将“lucy 1234 www”这个单词插入到 words 第二行下,打印。
    [admin@ datas]$ sed "2a lucy 1234 www" words
    (2)删除 words 文件所有包含 h 字母的行 
    [admin@ datas]$ sed "/h/d" words
    (3)将 words 文件中 h 字母替换为 H 字母 
    [admin@ datas]$ sed "s/h/H/g" words
    注意:‘g’表示 global,全部替换
    (4)将 words 文件中的第二行删除并将 h 字母替换为 H 字母 
    [admin@ datas]$ sed -e "2d" -e "s/h/H/g" words
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3.awk
    一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。

    基本用法
    
    awk [选项参数] ‘pattern1{action1} pattern2{action2}...’ filename
    
    • 1
    • 2
    • 3
    • pattern:表示 AWK 在数据中查找的内容,就是匹配模式
    • action:在找到匹配内容时所执行的一系列命令

    选项参数说明

    • -F: 指定输入文件折分隔符
    • -v(小写): 赋值一个用户定义变量
    (1)awk+action 简单示例 
    数据准备
    [admin@ datas]$ vim words 
    hello world !!
    hadoop spark hive 
    张三 李四 王五             
    找到 words 文件的第 1 列
    [admin@ datas]$ awk '{print $1}' words
    (2)awk+pattern+action 示例
    awk 可以使用正则
    搜索 passwd 文件,以:分隔,输出以 a 字母开头的所有行 
    [admin@ datas]$ awk -F ':' '/^a/{print $0}' passwd         
    搜索 passwd 文件,以:分隔,输出以 a 字母开头的所有行的第 1 列和第 6 列,两列之间加上--字符
    [admin@ datas]$ awk -F ':' '/^a/{print $1"--"$6}' passwd
    注意:有正则的时候,只有匹配了 pattern 的行才会执行 action
    搜索 passwd 文件,输出以 a 字母开头的所有行的第 1 列和第 6 列,以--分割,且在开头第一行的上面添加一行列名“1 列”“6 列”,以--分隔,在最后一行的下面添加一行内容"这是所有的以 a 开头的行的 1、6 两列"。
    [admin@ datas]$ awk -F ':' 'BEGIN{print "1 列--6 列"} /^a/{print $1"--"$6} END {print "这是所有的以 a 开头的行的 1、6 两列"}' passwd
    注意:BEGIN 在所有数据读取行之前执行;END 在所有数据执行之后执行。
    搜索 passwd 文件,输出以 a 字母开头的所有行的第 1 列和第 6 列,以空格分割,且在开头第一行的上面添加一行列名“行号”“1 列”“6 列”,以空格分隔,在最后一行的下面添加一行内容"这是所有的以 a 开头的行的 1、6 两列",并且给每一行一个行号(从 1 开始,以此类推,不包括开始和结束行)
    [admin@ datas]$ awk -v i=0 -F ':' \
    'BEGIN{print "行号","1 列","6 列"} \
    /^a/{print ++i,$1,$6} \
    END {print "这是所有的以 a 头的行的 1、6 两列"}' \ 
    passwd
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    运算符

    = += -= *= /= %= ^= **=   赋值
    ?:   C 条件表达式
    ||   逻辑或
    &&   逻辑与
    ~ 和 !~   匹配正则表达式和不匹配正则表达式
    < <= > >= != ==   关系运算符
    空格   连接
    +-   加,减
    * / %   乘,除与求余
    + - !    一元加,减和逻辑非
    ^ ***    求幂
    ++ --    增加或减少,作为前缀或后缀 $ 字段引用
    in    数组成员
    
    搜索 passwd 文件,输出以 a 字母开头的第 2、3 行的第 1 列和第 6 列,以空格分割,且在开头第一行的上面添加一行列名“行号”“1 列”“6 列”,以空格分隔,在最后一行的下面添加一行内容"这是所有的以 a 开头的行的 1、6 两列",并且给每一行一个行号 (从 1 开始,以此类推,不包括开始和结束行)
    [admin@ datas]$ awk -v i=0 -F ':' '/^a/{print ++i,$1,$6}' passwd | awk 'BEGIN{print "行号","1 列","6 列"} $1>=2&&$1<=3 {print $0} END {print "这是 所有的以a 头的行的1、6两列"}'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    print 和 printf

    [admin@ datas]$ vim person 
    张三 男 13          
    想要把上面 person 的内容输出为以下这样: 
    姓名:张三
    性别:男
    年龄:13
    使用 print,print 输出字符串,直接拼接
    [admin@ datas]$ awk '{print "姓名:"$1"\n 性别:"$2"\n 年龄:"$3}' person
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    使用 printf,printf 是格式化输出,语法格式为 printf 格式 参数

    [admin@ datas]$ awk '{printf ("姓名:%s\n 性别:%s\n 年龄:%d\n",$1,$2,$3)}' person
    
    • 1

    注意:printf 可以直接在命令行使用,但是在命令行中使用和在 awk 中有些区别直接使用是这样写

    [admin@ datas]$ printf "姓名:%s\n 性别:%s\n 年龄:%d\n" "张三" "男" 11
    
    • 1

    常用转义字符

     \" - 转义后的双引号 
     \\ - 转义后的反斜杠
     \b - 退格符 
     \n - 换行符
     \r - 回车符
     \t - 水平制表符 
     \v - 垂直制表符
     %% - 单个%符号
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    格式化常用的类型转换符

     %d - 将参数打印为十进制整数
     %f - 将参数打印为浮点数 
     %s - 将参数打印为字符串
     %x - 将参数打印为十六进制整数
     %o - 将参数打印为八进制整数
    
    • 1
    • 2
    • 3
    • 4
    • 5

    awk 的内置变量

    $n   当前记录的第 n 个字段,字段间由 FS 分隔
    $0    完整的输入记录
    ARGC    命令行参数的数目
    ARGIND    命令行中当前文件的位置(从 0 开始算) 
    ARGV    包含命令行参数的数组
    CONVFMT    数字转换格式(默认值为%.6g)
    ENVIRON    环境变量关联数组 
    ERRNO    最后一个系统错误的描述
    FIELDWIDTHS    字段宽度列表(用空格键分隔)
    FILENAME    当前文件名
    FNR    各文件分别计数的行号
    FS    字段分隔符(默认是任何空格)
    IGNORECASE    如果为真,则进行忽略大小写的匹配
    NF    一条记录的字段的数目
    NR    已经读出的记录数,就是行号,从 1 开始
    OFMT    数字的输出格式(默认值是%.6g)
    OFS    输出字段分隔符,默认值与输入字段分隔符一致。ORS 输出记录分隔符(默认值是一个换行符)
    RLENGTH    由 match 函数所匹配的字符串的长度
    RS    记录分隔符(默认是一个换行符)
    RSTART    由 match 函数所匹配的字符串的第一个位置 SUBSEP 数组下标分隔符(默认值是/034)
    
    (1)统计 passwd 文件名,每行的行号,每行的列数
    [admin@ datas]$ awk -F ':' '{printf ("文件名:%s,第%d 行有%d 列 \n",FILENAME,NR,NF)}' passwd
    (2)切割 IP(awk 有去空格)
    [admin@ datas]$ ifconfig | grep "inet" | head -n 1 | awk '{print $2}'
    (3)查询一个文件中所有空行所在的行号 数据准备
    [admin@ datas]$ vim space.txt
    [admin@ datas]$ awk '/^$/ {print NR}' space.txt
    (4)统计单词数
    [admin@mc datas]$ vim wordcount 
    hello world hello world
    hello hadoop spark hive hadoop 
    hive 李四
    使用 awk 统计查询 wordcount
    [admin@ datas]$ awk '{for(i=1;i<=NF;i++){arr[$i]++}} END{for(i in arr){print i,arr[i]}}' wordcount
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    注意:
    我们这里使用了 for 和 if,在命令行执行 awk 命令时,for 和 if 这些的写法基本上就与 java 很相似了。
    awk 中不用特意声明变量,第一次使用变量的地方就相当于声明。
    我们使用了数组,awk 中的数组除了数字做索引之外,也可以使用字符串做索引,我们这里就是使用的字符串做索引(这样就相当于 java 中的 map 集合了),数组元素如果是 null 也可以直接使用++计算。

    awk脚本

    awk 脚本中是要执行的 awk 逻辑,脚本以后缀为.awk,脚本开头是#!/bin/awk -f。

    awk 脚本执行是 awk -f 脚本 查询的目标文件

    使用 awkdemo.awk 脚本查询 words 文件 
    [admin@ datas]$ awk -f awkdemo.awk words
    
    之前使用 awk 命令行统计查询 wordcount
    [admin@ datas]$ awk '{for(i=1;i<=NF;i++){arr[$i]++}} END{for(i in arr){print i,arr[i]}}' wordcount
    把这个改成 awk 脚本执行
    [admin@ datas]$ vim count.awk 
    #!/bin/awk -f
    #遍历文件前
    #BEGIN{
    # 如果遍历前有逻辑,就在这里写 
    #}
    #遍历文件每一行时的逻辑 
    {
        for(i=1;i<=NF;i++){ 
        arr[$i]++
        } 
    }
    #遍历文件后 
    END{
    #如果遍历后有逻辑,在这里写 
    #我这里是输出汇总结果
        for(i in arr){ 
            print i,arr[i]
        }
    }
    执行这个脚本,统计 wordcount 文件的单词 
    [admin@ datas]$ awk -f count.awk wordcount
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    awk 内置函数

    算数函数

    atan2( y, x )   返回 y/x 的反正切。
    cos( x )    返回 x 的余弦;x 是弧度。
    exp( x )    返回 x 幂函数。
    log( x )    返回 x 的自然对数。
    sqrt( x )    返回 x 平方根。
    int( x )    返回 x 的截断至整数的值。
    rand( )   返回任意数字 n,其中 0 <= n < 1。
    srand( [Expr] )   将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。srand()括号内没有表达式的话,它会采用当前时间作为随机计数器的种子,这样以秒为间隔,rand()随机数就能滚动随机生成了
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    生成 3 次 10 以内的随机数

    [admin@ datas]$ vim demo.awk 
    #!/bin/awk -f
    BEGIN{
        srand() 
        for(i=0;i<3;i++){
            print int(rand()*10) 
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    字符串函数

    sub( Ere, Repl, [ In ] )
    
    • 1

    字符串替换,只替换第一次匹配的
    参数 1:被替换的字符串(具体的值或正则)
    参数 2:替换的新的字符串
    参数 3:被替换的字符串所属的变量(不填默认是 awk 的$0)

    gsub( Ere, Repl, [ In ] )
    
    • 1

    替换所有匹配的字符串
    参数含义与sub相同

    index( String1, String2 )
    
    • 1

    返回参数 2 作为参数 1 子串出现在参数 1 的哪个索引位置,从 1 开始。如果参数 2 不是参数 1 的子串,则返回 0。

    length [(String)]
    
    • 1

    返回 String 参数指定的字符串的长度(字符形式)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。

    blength [(String)]
    
    • 1

    返回 String 参数指定的字符串的长度(以字节为单位)。如果未给出 String 参数,则返回整个记录的长度($0 记录变 量)。

    substr( String, M, [N])
    
    • 1

    字符串截取
    参数 1:被截取的字符串
    参数 2:截取的子串开始位置索引值,从 1 开始
    参数 3:截取的子串的结束位置索引值,不填就是截取到结尾 返回值:截取的字符串,从 M 到 N 位置,不包括 N

    match( String, Ere )
    
    • 1

    在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式 出现在其中)中返回位置(字符形式),从 1 开始编号,如果 Ere 不存在,则返回 0(零)。

    split( String, A, [Ere] )
    
    • 1

    分割为数组
    参数 1:被分割的字符串
    参数 2:接收分隔的字符串数组
    参数 3:分隔的字符(固定值或者正则)

    tolower( String )
    
    • 1

    返回 String 参数指定的字符串,字符串中每个大写字符将更改 为小写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。

    toupper( String )
    
    • 1

    返回 String 参数指定的字符串,字符串中每个小写字符将更改 为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。

    sprintf(Format, Expr, Expr, . . . )
    
    • 1

    根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。

    (1)substr 字符串截取 [admin@mc datas]$ vim words 
    hello world !!
    hadoop spark hive
    张三 李四 王五
    截取输出 words 每一行的第 1 列的前 2 个字符
    [admin@ datas]$ awk '{print substr($1,1,2)}' words
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    awk 做大数据查询的简单应用

    [admin@ datas]$ vim grade.txt 
    #学号 科目 成绩
    1 语文 90
    1 数学 40
    1 英语 59
    2 语文 95
    2 数学 80
    2 英语 52
    3 语文 89
    4 数学 29
    (1)使用 awk 命令行,根据学号汇总查询每个学生的总成绩
    [admin@ datas]$ cat grade.txt | grep -v "#" | awk '{arr[$1]+=$3} END{for(i in arr){printf("学号为%d 的学生的成绩是:%d\n",i,arr[i])}}'
    (2)使用 awk 脚本,根据学号查询学生的总成绩,学号参数由外部输入,可以同时查询 多个学号
    可以使用 awk -f xxx.awk -v 参数名=参数值 参数名=参数值 查询的目标文件这样的方式 给 awk 脚本传参
    
    [admin@ datas]$ vim grade-no.awk
    #!/bin/awk -f
    { arr[$1]+=$3
    }
    END{
    #接收参数名为 no 的外部参数,参数 no 的值是学号,可以多个
    #多个值时用英文逗号分隔
    #使用 split 函数切割 no 的字符串,分隔符是英文逗号, 
    #用变量 nos 接收切割后的数组
    split(no,nos,",")
    for(i in nos){
        cno=nos[i]
        printf("学号为%d 的学生的成绩是:%d\n",cno,arr[cno])
        }
    }
    执行 awk 脚本,查询学号为 2 和 4 的学生的总成绩
    [admin@ datas]$ awk -f grade-no.awk -v no="2,4" grade.txt
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
  • 相关阅读:
    Polarion javascript 修改工作项状态
    Ant-Design-Pro-V5 :QueryFilter高级筛选组件、Table以及Pagination组件结合实现查询。
    微信小程序入门---超详细教程
    重磅:百度李彦宏、中科院曾毅入选,《时代周刊》AI最有影响力100人!
    Spring-Java
    2022-09-07 mysql/stonedb-查询优化器逻辑记录及优化器魔改
    Android内核模块编译
    linux读取U盘操作
    【scikit-learn基础】--『预处理』之 标准化
    SpringCloud GateWay 万字详解
  • 原文地址:https://blog.csdn.net/qq11771258/article/details/132907703