Linux Shell Script脚本(bash)一篇快速上手入门

本文详细介绍了Shell脚本的基础知识,包括Shell的用途、常用的Shell类型如bash和dash,以及如何编写和运行.sh文件。文章还讲解了变量的定义、赋值、运算以及条件判断和循环控制结构,展示了如何在Shell脚本中进行计算和逻辑控制。此外,还涵盖了函数的使用和文件归档的脚本示例。
摘要由CSDN通过智能技术生成

Shell Script

概述

Shell是命令行解释器,它接受应用程序或用户命令,然后调用操作系统内核。

Shell可以嵌套

  • 使用exit命令可以退出当前shell。

在这里插入图片描述

Shell 脚本(shell script)是种为 shell 编写的脚本程序。常说的shell通常都是指 shell 脚本,但shell和shell script是两个不同的概念。通常说“shell编程”都是指 shell 脚本编程,不是指开发 shell 自身。

  • sh(Bourne Shell)是个早期的重要shell,1978年由史蒂夫·伯恩编写,并同Version 7 Unix一起发布。

  • bash(Bourne-Again Shell)是为GNU计划编写的Unix shell。1987年由布莱恩·福克斯创造。主要目标是与POSIX标准保持一致,同时兼顾对sh的兼容,是各种Linux发行版标准配置的Shell,在Linux系统上/bin/sh往往是指向/bin/bash的符号链接。

  • dash (Debian Almquist shell)一种 Unix shell。它比 Bash 小,只需要较少的磁盘空间,但是它的对话性功能也较少。它由 NetBSD版本的Almquist shell (ash)发展而来,于1997年由赫伯特·许(Herbert Xu)移植到Linux上,于2002年改名为 dash。

脚本以#!/bin/sh#!/bin/bash#!/bin/dash开头,用于指定解析器。

来写个Hello Shell

  • #!/bin/sh
    echo "Hello Shell!"
    

Linux下面用命令如何运行.sh文件的方法

  1. 直接./加上文件名.sh,如运行hello.sh为./hello.sh【hello.sh必须有x权限,即执行权限】
  2. 直接shbash加上文件名,如运行hello.sh为sh hello.sh【hello.sh无需x权限,即执行权限】
  3. source或者.(简写),都能实现和sh一样的效果。但不同点在于,前面的方式会创建子shell(启动了个sh进程),在子shell里执行命令,而source方式直接在当前shell执行。

变量

系统预设变量

前面提到子shell的存在,使不使用的区别就在于环境变量的继承关系。在子shell设置的当前变量,父shell是不可见的。

常用系统变量:HOME、PWD、SHELL、USER

全局变量与局部变量

  • 全局变量在本shell及所有子shell可见(父shell不可见),局部变量只在当前shell可见。
  • envprintenv命令查看所有全局变量
    • printenv <variable>:打印指定的全局变量
  • echo $<variable>,echo命令配合$符也可以打印变量。
  • set运行不带选项或参数的命令会输出所有设置的列表——所有 shell 变量和函数的名称和值。
  • shell里直接打印不存在的变量并不会报错,而是输出空。

用户自定义变量

基本语法

  • 定义变量:<variable>=<value>
    • =号前后不能有空格,在shell中无需指定变量类型。
    • 有空格的情况可以使用引号,例如variable="Hello variable"
    • 属于局部变量,子shell不可见。
  • 导出变量
    • 自定义的变量默认局部变量,但是可以通过export语句导出为全局变量。
    • 语法:export <variable>
  • 修改变量
    • 修改变量值只对变量所在的shell及子shell生效,也就是说子shell的修改不会对父shell造成影响。

深入学习变量

变量默认为字符串

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ numberX=1+5
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $numberX 
    1+5
    

使用$((<expression>))$[<expression>],括号里放表达式。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ numberY=$((6+6))
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $numberY
    12
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ numberU=$[9+9]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $numberU
    18
    

使用readonly关键字可以让变量只读

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ readonly readonlyX="Hello readonly"
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $readonlyX 
    Hello readonly
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ readonlyX="Change test"
    bash: readonlyX: readonly variable
    

撤销指定变量

  • 使用unset <variable>,即可撤销指定变量。
  • readonly变量无法撤销。

特殊变量

PATH。对应当前配置的环境变量。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $PATH
    /home/xuegao/.config/nvm/versions/node/v18.14.0/bin:/usr/local/app/maven/apache-maven-3.6.3/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/sbin:/usr/sbin:/snap/bin:/usr/local/app/hadoop-3.3.2/bin:/opt/app/kafka/kafka_2.13-3.1.0/bin
    
  • 可以看到除了系统的binsbin这些,还有node、maven、hadoop等环境变量,这都是我自己配置在该机器的,将路径添加到环境变量后,可以直接执行该路径下的可执行文件——在任何地方。就像下面查看nodejs版本一样。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ node -v
    v18.14.0
    

$<number>。number为数字,$0表示当前脚本名称(绝对路径),$1 ~ $9代表一到九个参数,十以上的参数需要用大括号包含${<number>},例如$<11>

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat helloShell.sh
    #!/bin/sh
    echo "这里是$0脚本"
    echo "Hello $1"
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./helloShell.sh 参数一
    这里是./helloShell.sh脚本
    Hello 参数一
    

$#。获取所有输入参数个数,常用于循环判断参数的个数是否正确,以及加强脚本的健壮性。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat paramater.sh
    #!/bin/sh
    echo script name: $0
    echo 1st paramater: $1
    echo 2st paramater: $2
    echo parameter numbers: $#
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ sh paramater.sh a b
    script name: paramater.sh
    1st paramater: a
    2st paramater: b
    parameter numbers: 2
    

$*$@。两者都是代表命令行中所有的参数,不过$*是字符串,$@是实际的数组。若不加双引号,两者是一样的。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat paramater.sh
    #!/bin/sh
    echo script name: $0
    echo 1st paramater: $1
    echo 2st paramater: $2
    echo parameter numbers: $#
    echo $*
    echo $@
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ sh paramater.sh a b
    script name: paramater.sh
    1st paramater: a
    2st paramater: b
    parameter numbers: 2
    a b
    a b
    

$?。最后一次执行的命令的返回状态。若值为0,表正确执行了;若不为0(具体是啥,由命令自己决定),则证明上个命令执行不正确;

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ ls
    helloShell.sh  paramater.sh
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    0
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ fajefpewi
    -bash: fajefpewi: command not found
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    127
    

运算符

使用expr关键字可以实现计算功能,要注意参数之间用空格隔开,否则会被视为字符串。另外,像*号由于默认视为通配符,所以要使用\表示视其为普通的*号。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ expr 5 + 5
    10
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ expr 5 \* 5
    25
    

前面提到过使用[]或者(())的方式实现运算,只要把表达式放到里面就好了。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $[6 / 2]
    3
    

赋值。下面分别展示两者运算后的赋值方法。$(<command>)实现命令替换功能,执行内部的command,然后输出到指定位置。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ var_a=$((6*6))
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $var_a
    36
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ var_b=$(expr 4 - 5)
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $var_b
    -1
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ var_c=`expr 5 + 6`
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $var_c
    11
    

写个加法脚本

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat add.sh
    #!/bin/sh
    sum=$(($1+$2))
    echo sum=$sum
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./add.sh 34 43
    sum=77
    

条件判断

判断状态

使用test关键字,语法为test <condition>,下面是示例,使用$?获取语句执行状态(0true)。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $var_a
    hello
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ test $var_a = HELLO
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    1
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ test $var_a = hello
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    0
    

使用[ <condition> ],虽然也是中括号,但不同于前面的是,要求前后都留有空格。

  • 条件非空即为true,例如。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ [ hello ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    0
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ [  ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    1
    

常用判断条件

两个整数之间比较

比较符

  • -eq:等于,equal。
  • -ne:不等于,not equal。
  • -lt:小于,less than。
  • -le:小于等于,less equal。
  • -gt:大于,greater than。
  • -ge:大于等于,greater equal。

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ [ 4 -ge 4 ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    0
    

注意如果使用(())语法,那么括号内是可以直接使用<>=符号的。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ if ((1 > 2)); then echo YES; else echo NO; fi
    NO
    

判断文件是否有对应权限

断言符

  • -r:读,read。
  • -w:写,write。
  • -x:执行,execute。

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ ll
    total 12
    -rwxr-xr-x 1 xuegao xuegao  39 Mar  7 00:07 add.sh
    -rwxr-xr-x 1 xuegao xuegao  51 Mar  6 01:13 helloShell.sh
    -rw-r--r-- 1 xuegao xuegao 120 Mar  7 00:03 paramater.sh
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ [ -x paramater.sh ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ echo $?
    1
    

按照文件类型进行判断

断言符

  • -e:文件存在,existence。
  • -f:文件存在且为常规文件,file。
  • -d:文件存在且为目录,directory。

连接符

&&表示上条命令执行成功时,执行下条命令;||表示上条命令执行失败后,执行下条命令;

示例:

xuegao@xuegao-PC:~/dev/workspace/script/shell$ ls
add.sh  helloShell.sh  paramater.sh
xuegao@xuegao-PC:~/dev/workspace/script/shell$ test -f add.sh && echo OK
OK
xuegao@xuegao-PC:~/dev/workspace/script/shell$ test -f addddd.sh && echo OK
xuegao@xuegao-PC:~/dev/workspace/script/shell$ test -f addddd.sh && echo OK || echo failer
failer

流程控制

if 判断

单分支,有两种写法。

  • if [ <condition> ]; then
    	#code……
    fi
    
  • if [ <condition> ]
    then
    	#code……
    fi
    

表达式可以使用连接符,下面是例子

  • xuegao@LAPTOP-XUEGAO:~/temp/script$ echo $a
    23
    xuegao@LAPTOP-XUEGAO:~/temp/script$ if [ $a -gt 18 ] && [ $a -lt 36 ]; then echo OK; fi
    OK
    

另外还支持在括号内使用-a-o来表示and、or。

  • xuegao@LAPTOP-XUEGAO:~/temp/script$ if [ $a -gt 18 -a $a -lt 36 ]; then echo OK; fi
    OK
    

多分支使用elifelse来实现,下面是示例。

  • #!/bin/sh
    if [ $1 -lt 18 ]
    then
            echo "未成年人"
    elif [ $1 -lt 35 ]
    then
            echo "青年人"
    elif [ $1 -lt 60 ]
    then
            echo "中年人"
    else
            echo "老年人"
    fi
    

case 语句

语法

  • case $var in
    <value1>)
    	#code
    ;;
    <value2>)
    	#code
    ;;
    *)
    	#default code
    esac
    

示例

  • #!/bin/sh
    
    case $1 in
    1)
            echo "one"
    ;;
    2)
            echo "two"
    ;;
    3)
            echo "three"
    ;;
    *)
            echo "other figures"
    ;;
    esac
    

for 循环

((;;))方式

语法

  • for (( <initial value>;<cycle control coditions>;<change variables> ))
    do
    	#code
    done
    

示例

  • #!/bin/bash
    sum=0
    for ((i=1;i<=$1;i++))
    do
            sum=$[$sum+$i]
    done
    echo $sum
    

for i in xx xx方式

语法(item array表元素数组)

  • fro <variable> in <element array>
    do #code
    d
    

示例

  • for os in linux windwos macos; do echo $os; done
    linux
    windwos
    macos
    

另外,shell支持{n..m}这种语法,下面是例子。{1..100}表示从1到100的数组,所以下面的for循环会执行一百次。

  • xuegao@xuegao-PC:~/dev/workspace/script$ for i in {1..100}; do sum=$[$sum+$i]; done; echo $sum
    5050
    

前面特殊变量章节提到过$@*、$@`,它俩也可以作为数组供给for循环使用。当加上双引号时,表现会所有不同。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat forIn.sh 
    #!/bin/bash
    
    echo '$*============================'
    for param in "$*"
    do
            echo $param
    done
    
    echo '$@============================'
    for param in "$@"
    do
            echo $param
    done
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./forIn.sh a b c 
    $*============================
    a b c
    $@============================
    a
    b
    c
    

while 循环

语法

  • while [ <condition> ]
    do #code
    done
    

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat while.sh 
    #!/bin/bash
    a=1
    sum=0
    while [ $a -le $1 ]
    do
            sum=$[ $sum + $a ]
            a=$[ $a + 1 ]
    done
    echo $sum
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./while.sh 100
    5050
    

这种夹杂着$和中括号的写法实在是太丑陋了,但使用let关键字可以让写法优雅许多。

  • let 是 Bash 的内置函数,它允许我们进行简单的算术运算。语法是let <arithmetic expression>

下面是使用let的代码块,清爽得多,效果同上是一样的。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat whileLet.sh 
    #!/bin/bash
    a=1
    sum=0
    while [ $a -le $1 ]
    do
            let sum+=a
            let a++
    done
    echo $sum
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./whileLet.sh 100
    5050
    

读取console输入

语法

  • read <optional> <parameter>
    • optional
      • -p指定读取值时的提示符;
      • -t指定读取值时等待的时间(秒),若不指定表示无限等待;
    • parameter
      • 指定读取值对应的变量

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat read.sh 
    #!/bin/bash
    read -t 30 -p "你的称呼是:" name
    echo "欢迎$name使用本程序"
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ bash read.sh
    你的称呼是:雪糕
    欢迎雪糕使用本程序
    

函数

系统函数

basename

语法:basename <pathname> <suffix>

功能

  • basename命令会删除所有的前缀,以及最后的/符,最后打印结果。
  • suffix是可选的后缀项,若指定了,则去除对应后缀。

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ basename ~/dev/workspace/script/shell/add.sh
    add.sh
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ basename ~/dev/workspace/script/shell/add.sh .sh
    add
    

dirname

语法:dirname <pathname>

功能:去掉文件名,获取路径。

示例(获取绝对路径)

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dirname.sh 
    #!/bin/bash
    cd $(dirname $0)
    echo $(pwd)
    xuegao@xuegao-PC:~/temp$ bash ../dev/workspace/script/shell/dirname.sh 
    /home/xuegao/dev/workspace/script/shell
    

自定义函数

语法

  • <function> functionName(){
    	#action;
    	[return int;]
    }
    

注意

  • 必须先声明函数和,才能调用。因为shell是逐行运行。
  • 函数返回值通过$?获取,函数通过return显式返回,或使用最后一条命令的运行结果。如果使用return的话,返回值要求为0~255。

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat functionTest.sh 
    #!/bin/bash
    
    function add(){
            sum=$[$1 + $2]
            echo $sum
    }
    
    read -p "输入整数a:" a
    read -p "输入整数b:" b
    
    result=$(add a b)
    echo 求和结果为:$result
    echo 和的平方:$[ $result * $result ]
    
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ ./functionTest.sh
    输入整数a:12
    输入整数b:34
    求和结果为:46
    和的平方:2116
    

归档文件

需求场景

  • 写个每天对指定目录归档备份的脚本,并将归档日期作为文件名后缀,文件归档到~/temp/archive。

脚本

  • #!/bin/bash
    
    #判断参数个数是否为1
    if [ $# -ne 1 ]
    then
    	echo 参数数量不为一个
    	exit
    fi
    
    #判断是否为目录
    if [ -d $1 ]
    then
    	echo 
    else
    	echo 目录不存在
    	exit
    fi
    
    DIR_NAME=$(basename $1)
    DIR_PATH=$(cd $(dirname $1); pwd)
    
    #获取当前日期
    DATE=$(date +%y%m%d)
    
    #定义生成的归档文件名称
    FILE=archive_${DIR_NAME}_${DATE}.tar.gz
    DEST=~/temp/archive/$FILE
    
    #归档文件
    echo 开始归档……
    tar -czf $DEST $DIR_PATH/$DIR_NAME
    
    if [ $? -eq 0 ]
    then
    	echo 归档成功
    	echo 归档文件名为:$DEST
    else
    	echo 归档出错
    fi
    
    exit
    

使用crontab管理定时任务

  • 0 2 * * * /home/xuegao/dev/workspace/script/shell/dailyArchive.sh /home/xuegao/temp/archive
    

正则

常规匹配

在Linux中,grep、sed、awk等文本处理工具,都支持通过正则表达式进行模式匹配。

匹配文本,例如下面匹配DIR_NAME字符串。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep DIR_NAME
    DIR_NAME=$(basename $1)
    FILE=archive_${DIR_NAME}_${DATE}.tar.gz
    tar -czf $DEST $DIR_PATH/$DIR_NAME
    

使用^指定前缀匹配

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep ^if
    if [ $# -ne 1 ]
    if [ -d $1 ]
    if [ $? -eq 0 ]
    

$匹配后缀

  • if [ $? -eq 0 ]
    xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep gz$
    FILE=archive_${DIR_NAME}_${DATE}.tar.gz
    

.匹配任意一个字符

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep arch..e
    FILE=archive_${DIR_NAME}_${DATE}.tar.gz
    DEST=~/temp/archive/$FILE
    

*不单独使用,和前个字符连用,表示前个字符出现任意次。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat helloShell.sh | grep Hel*
    echo "Hello $1"
    

小技巧

  • 连用^$可以匹配空行,使用grep -n ^$可以匹配空行并显示行号。
  • 连用.*匹配任意字符任意次

常用特殊字符

字符区间。[]:表示某个范围内的一个字符。

  • [6,8]:匹配6或8(逗号可省略)
  • [0-9]:匹配一个0至9的数字
  • [0-9]*:任意长度的数字
  • [a-z]:匹配一个a到z的字母
  • [a-z]*:匹配任意长度的字母
  • [a-c,e-f]:匹配a到c,或者e至f之间的一个字符。

特殊字符使用\避免被转义,要注意使用\的话,必须要将匹配文本使用引号包裹起来。下面是示例如何匹配$。

  • xuegao@xuegao-PC:~/dev/workspace/script/shell$ cat dailyArchive.sh | grep "\$1"
    if [ -d $1 ]
    DIR_NAME=$(basename $1)
    DIR_PATH=$(cd $(dirname $1); pwd)
    

下面是个匹配国内手机号的示例,其中grep添加-E参数表示支持regular expression扩展语法。({9}就是扩展语法,表示前面的规则重复9次)

  • echo "13899889988" | grep -E ^1[3456789][0-9]{9}$
    

文本处理工具

cut

cut的工作就是剪切,负责剪切文件数据。

语法

  • cut <optional parameter> <filename>
  • 可选参数
    • -f:列号,提取第几列。
    • -d:分隔符,按照指定分隔符分割列,默认为制表符\t
    • -c:按字符进行切割,后加n表示取第几列。

按空格分隔示例

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ cat state.txt 
    Andhra Pradesh
    Arunachal Pradesh
    xuegao@xuegao-PC:~/dev/workspace/script/text$ cut -d " "  -f 1 state.txt 
    Andhra
    Arunachal
    xuegao@xuegao-PC:~/dev/workspace/script/text$ 
    

-f参数支持同时提取多列

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ cat note.txt 
    14      1       Lombok
    15      1       Jackson
    xuegao@xuegao-PC:~/dev/workspace/script/text$ cut -f 1,3 note.txt 
    14      Lombok
    15      Jackson
    

-f参数还支持-语法

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ cut -f -2 note.txt 
    14      1
    15      1
    xuegao@xuegao-PC:~/dev/workspace/script/text$ cut -f 2- note.txt 
    1       Lombok
    1       Jackson
    

awk

常规使用

强大的文本分析工具,逐行读入,默认以空格为分隔符进行切片,再进行分析处理。

语法

  • awk <options> '/<regular expression>/ {<action>}' <input-file>
    • 根据正则表达式,从input-file获取文本,并以此执行action。action里执行代码。
  • awk <options> '/<regular expression>/ {<action>}' <input-file> > <output-file>
    • 同上,并输出结果到output-file。
  • options参数
    • -F:指定文件分隔符
    • v:赋值一个用户自定义变量

示例

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ cat employee.txt 
    ajay manager account 45000
    sunil clerk account 25000
    varun manager sales 50000
    amit manager account 47000
    tarun peon sales 15000
    deepak clerk sales 23000
    sunil peon sales 13000
    satvik director purchase 80000 
    xuegao@xuegao-PC:~/dev/workspace/script/text$ awk '/sa..s/ {print $1","$2}' employee.txt 
    varun,manager
    tarun,peon
    deepak,clerk
    sunil,peon
    

拓展:BEGIN再所有数据读取之前执行,END在所有数据执行之后执行。

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ cat employee.txt | awk 'BEGIN{print "开始"} {print $1","$2} END{print "结束"}'
    开始
    ajay,manager
    sunil,clerk
    varun,manager
    amit,manager
    tarun,peon
    deepak,clerk
    sunil,peon
    satvik,director
    结束
    
变量

使用-v参数

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ awk -v i=1 '/sa..s/ {print $1,$2,i}' employee.txt 
    varun manager 1
    tarun peon 1
    deepak clerk 1
    sunil peon 1
    

内置变量

  • FILENAME:文件名
  • NR:已读的记录数(行号)
  • NF:浏览记录的域个数(切割后,列的个数)

内置变量使用示例

  • xuegao@xuegao-PC:~/dev/workspace/script/text$ awk '/sa..s/ {print "文件名:"FILENAME ",行号:"NR ",列数:"NF}' employee.txt 
    文件名:employee.txt,行号:3,列数:4
    文件名:employee.txt,行号:5,列数:4
    文件名:employee.txt,行号:6,列数:4
    文件名:employee.txt,行号:7,列数:4
    

综合应用案例

发送消息

利用Linux自带的mesg和write工具,向其他用户发送消息。

需求

  • 向某个用户发送消息的脚本,参数为用户名和消息。
  • 脚本需要检测用户是否登录再系统中,是否打开了消息功能,以及当前发送的消息是否为空。

脚本

  • #!/bin/bash
    
    #截取用户信息
    loginUser=$(who | grep -i -m 1 $1 | awk '{print $1}')
    
    #-z用于判断字符串是否为空
    if [ -z $loginUser ]
    then
            echo "$1 不在线"
            echo "退出当前脚本"
            exit
    fi
    
    #判断是否开启了mesg
    allowed=$(who -T | grep -i -m 1 $1 | awk '{print $2}')
    
    if [ $allowed != "+" ]
    then
            echo "$1 没有开启消息功能"
            echo "退出当前脚本"
            exit
    fi
    
    #确认是否有消息发送
    if [ -z $2 ]
    then
            echo "没有可发送的消息"
            echo "退出当前脚本"
            exit
    fi
    
    #获取消息
    wholeMessage=$(echo $* | cut -d " " -f 2-)
    
    #获取终端
    userTerminal=$(who | grep -i -m 1 $1 | awk '{print $2}')
    
    #发送消息
    echo $wholeMessage | write $loginUser $userTerminal
    
    echo $wholeMessage
    echo $loginUser
    echo $userTerminal
    
    if [ $? -eq 0 ]
    then
            echo "发送成功"
    else
            echo "发送失败"
    fi
    
    exit
    
  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值