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

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
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux shell脚本编程是在Linux系统上使用shell进行编程的方式。常用的shellbash、sh、csh、tcsh等。 入门步骤如下: 1. 创建一个文本文件,文件名以".sh"结尾,表示这是一个shell脚本。 2. 编写脚本内容,脚本内容主要由Linux命令和shell语句组成。 3. 修改文件权限,使脚本文件可执行。 4. 运行脚本,通过在终端中输入“./脚本文件名”来执行脚本。 编写一个简单的脚本示例: ``` #!/bin/bash echo "Hello, World!" ``` 第一行表示使用bash shell来执行这个脚本 第二行是一个命令,输出一个字符串 执行方式: ``` chmod +x script_name.sh ./script_name.sh ``` 如果想了解更多关于Linux shell脚本编程的知识,可以参考Linux shell教程或者使用"man bash"命令来查看bash命令手册。 ### 回答2: Shell是一个命令解释器,是Linux/Unix系统中的一种重要工具,它提供了一个命令行界面,允许用户与操作系统进行交互。Shell脚本编程是将一系列Shell命令进行组合,以解决自动化任务、文件操作、编译工具和其他日常任务的编程技术。 Shell脚本是一个文本文件,文件名通常以“.sh”作为后缀名。脚本文件以#! /bin/bash或#! /bin/sh等开头,然后是脚本命令。在Shell脚本编程中,需要掌握以下几个方面: 1.基本语法:Shell脚本语法和其他编程语言一样,包括变量定义、数学计算、逻辑控制、循环操作等。 2.变量:Shell脚本中使用变量存储数据,可以通过赋值运算符“=”定义变量,也可以通过参数传递给脚本。需要注意的是,Shell变量不需要显式声明数据类型,也不能用“$”前缀定义变量。 3.重定向:Shell脚本中通过重定向符“>”、“>>”、“<”和“<<”来控制标准输入/输出和错误输出,非常方便输出数据和错误信息以及读取文件数据。 4.管道:Shell脚本中使用“|”符号来建立管道,将一个命令的输出作为另一个命令的输入,实现数据流的处理和转换功能。 5.循环和分支:在Shell脚本编程中,循环和分支语句的使用非常重要,可以实现复杂的逻辑功能,例如for、while、until循环和if、case语句。 在实际应用中,Shell脚本可以用于各种系统自动化操作,例如服务器备份、日志分析、批量文件操作、软件编译、自动安装等。此外,Shell脚本还可以与其他编程语言(例如Python、Perl)结合使用,形成更强大的脚本解决方案。 总的来说,Shell脚本编程是Linux系统中非常重要的一项技能,掌握Shell脚本基础语法和常用命令是必须的,可以帮助您更高效地完成日常的操作和管理任务。掌握Shell脚本编程后,您可以更深入地理解Linux系统工作原理,提高自身的技术水平和工作效率。 ### 回答3: Linux shell脚本编程是一种编写通用命令行脚本的方法。在 Linux 系统中,shell是一个命令行解释器,可以执行用户输入的命令。通过编写shell脚本,我们可以轻松地将多个Linux命令整合在一个脚本中,自动化完成一系列工作。 在学习 Linux shell脚本编程之前,需要掌握基本的Linux命令和shell语法,比如条件判断、循环等基本语句。另外,了解Linux文件系统、文件读写等操作也是必备的知识。 从最简单的开始,编写一个输出Hello World的脚本: ```bash #!/bin/bash # 指定使用哪种shell echo "Hello World!" # 输出Hello World ``` 在这个例子中,我们使用了 `#!/bin/bash` 来声明我们使用的是Bash shell,并使用 `echo` 命令输出一个字符串。 接下来,我们可以学习基本的控制语句,例如条件语句和循环语句。条件语句可以用来根据变量值来执行不同的命令: ```bash #!/bin/bash var="Hello World!" if [ $var == "Hello World!" ]; then echo "Equal!" else echo "Not equal." fi ``` 在这个例子中,我们使用 `if` 和 `else` 语句来判断变量的值是否等于“Hello World!”,然后根据结果执行相应的命令。 另一个常见的控制语句是循环语句,可以用于重复执行一组命令: ```bash #!/bin/bash for i in 1 2 3 4 5 do echo "Number: $i" done ``` 在这个例子中,我们使用 `for` 循环来输出数字1-5。 除了基本的控制结构,shell脚本还支持参数处理和函数定义等高级语法。使用 `getopts` 命令可以方便地解析脚本参数: ```bash #!/bin/bash USAGE="Usage: $0 -f <filename> -n <num_lines>" while getopts ":f:n:" opt; do case $opt in f) file=$OPTARG ;; n) num_lines=$OPTARG ;; \?) echo "Invalid option: -$OPTARG" >&2 echo "$USAGE" >&2 exit 1 ;; :) echo "Option -$OPTARG requires an argument." >&2 echo "$USAGE" >&2 exit 1 ;; esac done echo "Printing $num_lines lines from $file:" head -n $num_lines $file ``` 在这个例子中,我们使用 `getopts` 命令和 `case` 语句来解析脚本参数,然后根据参数执行相应的命令。 最后,我们还可以定义函数,用于重复使用一组命令: ```bash #!/bin/bash function print_number { echo "Number: $1" } for i in 1 2 3 4 5 do print_number $i done ``` 在这个例子中,我们定义了一个名为 `print_number` 的函数,函数以一个参数为输入并输出字符串。 通过学习以上例子,我们可以了解到Linux shell脚本编程的基础语法和基本知识。在实践中,我们可以根据实际需求编写多种脚本来完成不同的任务,使Linux系统自动化执行一系列操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值