shell函数和三剑客

发布时间 2023-05-23 22:28:15作者: fdsimin

函数

基本语法

# 写法一:
function 函数名(){
  函数要执行的命令  
}

# 写法二,省略():
function 函数名 {
  函数要执行的命令  
}

# 写法三,省略function:
函数名 () {
  函数要执行的命令  
}

# 调用函数
# 没有参数的函数
函数名
# 有参数的函数
函数名 参数一 参数二

函数的返回值

# return 返回1-255的整数,0表示正确执行,其他数字表示没有正确执行
[root@head test]# cat test.sh 
#!/usr/bin/bash

export aaa=123

function test() {
    a=123
    echo $a
    return 0
}
test

# echo 返回字符串,可定义变量接收函数的返回值
[root@head test]# cat test.sh 
#!/usr/bin/bash

export aaa=123

function test() {
    a=123
    echo $a
}
bbb=`test`
echo $bbb

代码示例

# 代码示例一:
[root@head test]# cat test.sh 
#!/usr/bin/bash

function test() {
    echo $#
    echo $@
    echo $*
    echo $1
    echo $?
}
test 1 2 3 4 5 6

# 代码示例二:
# 函数内的return的结果是指函数的状态,0代表成功,其他代表失败
# 示例二中执行完脚本后,用$?获取状态为1
[root@head test]# cat test.sh 
#!/usr/bin/bash

function test() {
    echo 111
    return 1
}

# 代码示例三:
# local的使用,用local定义局部变量。shell中定义的变量,默认都是全局变量,此示例中如果不用local,则第二个$a也是有值的
[root@head test]# cat test.sh 
#!/usr/bin/bash

function test() {
    local a=123
    echo $a
}

test
echo $a # 值为空
test

# 说明:如果在当前进程中引用了脚本,则脚本中的变量也会生效
[root@head test]# bash test.sh 
123
123
[root@head test]# 
[root@head test]# echo $a

[root@head test]# source test.sh
123
123
[root@head test]# echo $a
123

 grep

在文件中查找内容的状态

# 正常查找
[root@head ~]# grep "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@head ~]# echo $?
0

# 查找不到内容
[root@head ~]# grep "aaaaaaa" /etc/passwd
[root@head ~]# echo $?
1

# 后面跟的文件不存在
[root@head ~]# grep "root" /etc/password
grep: /etc/password: No such file or directory
[root@head ~]# echo $?
2

grep参数详解

# -n --line-number 显示查找到的内容在文件中的行号
[root@head ~]# grep -n "root" /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin

# -o --only-matching 只显示需要匹配的内容
[root@head ~]# grep -o "root" /etc/passwd
root
root
root
root

# -q --quiet 静默输出,可用$?获取匹配是否成功
[root@head ~]# grep -q "root" /etc/passwd
[root@head ~]# echo $?
0

# -i --ignore-case 忽略大小写
[root@head test]# grep -i "a" ./ccc01.txt 
aaa
AAA

# -A --after-context=NUM 如果匹配成功,则将其后面N行也打印出来
[root@head ~]# grep -A 2 "mysql" /etc/passwd
mysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin
influxdb:x:299:299:user for InfluxDB database server:/var/lib/influxdb:/sbin/nologin
ldap:x:55:55:OpenLDAP server:/var/lib/ldap:/sbin/nologin

# -B --before-context=NUM 如果匹配成功,则将其前面N行也打印出来
[root@head ~]# grep -B 2 "mysql" /etc/passwd
epmd:x:987:981:Erlang Port Mapper Daemon:/dev/null:/sbin/nologin
rabbitmq:x:984:980:RabbitMQ messaging server:/var/lib/rabbitmq:/sbin/nologin
mysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin

# -C  --context=NUM 如果匹配成功,则将其上写N行也打印出来
[root@head ~]# grep -C 1 "mysql" /etc/passwd
rabbitmq:x:984:980:RabbitMQ messaging server:/var/lib/rabbitmq:/sbin/nologin
mysql:x:27:27:MySQL Server:/var/lib/mysql:/sbin/nologin
influxdb:x:299:299:user for InfluxDB database server:/var/lib/influxdb:/sbin/nologin

#-c --count 如果匹配成功,将匹配成功的行数打印出来
[root@head ~]# grep -c "root" /etc/passwd
2

# -v --invert-match 取反,将不匹配的行打印出来
[root@head test]# grep -i -v "a" ./ccc01.txt 
vvv

-r --recursive 递归匹配

# -l --files-with-matches 如果文件内容有匹配成功的,则将文件名打印出来
[root@head test]# grep -rl "a" /home/test

# -w 匹配整个单词
[root@head test]# grep -w "test" ./ccc01.txt 
test
[root@head test]# netstat -nltp | grep -w 80
tcp6 0 0 :::80 :::* LISTEN 1132/httpd
# -E 相当于egrep扩展

grep正则匹配示例

# ^ 匹配开头
[root@head test]# grep ^root /etc/passwd
root:x:0:0:root:/root:/bin/bash

# $ 匹配结尾
[root@head test]# grep "shutdown$" /etc/passwd
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

# . 匹配任意一个字符
[root@head test]# grep "a." ./ccc01.txt 
atest
atesta

# * 匹配0个或多个字符
[root@head test]# grep "a*" ./ccc01.txt 
atest
test
atest

# .* 匹配所有字符
[root@head test]# grep "a.*" ./ccc01.txt 
atest
atesta

# [] 匹配字符组内的任意字符
[root@head test]# grep [at] ./ccc01.txt 
atest
test
atesta

# [^] 取反,不匹配字符组内的所有字符
[root@head test]# grep [^at] ./ccc01.txt 
atest
test
atesta

sed

sed选项

# -e 允许多项编辑
[root@head test]# cat ccc01.txt 
atest
test
atesta
[root@head test]# 
[root@head test]# sed -e '1d' -e '3d' ccc01.txt 
test

# -n 取消模式空间的内容输出
[root@head test]# sed -n -e '1d' -e '3d' ccc01.txt 
[root@head test]#

# -i 将修改内容保存到文件中
[root@head test]# sed -i -e '1d' -e '3d' ccc01.txt 
[root@head test]# cat ccc01.txt 
test

# -f 指定sed脚本的文件名
# -r 支持扩展元字符

sed常用命令

# a 追加命令,前面指定在文件的第N行追加
[root@head test]# sed "2a111" ccc01.txt 
atest
test
111
atesta

# c 修改命令,用当前文本修改文件中的第N行
[root@head test]# sed "2c111" ccc01.txt 
atest
111
atesta

# d 删除命令,删除文件中的第N行
[root@head test]# sed "2d" ccc01.txt 
[root@head test]# sed "/atest/d" ccc01.txt 
test

# i 插入命令
[root@head test]# sed "2i111" aa.txt 
atest
111
test
atesta

# s 替换命令,替换文件中的内容
[root@head test]# sed "s/test/real/" aa.txt 
areal
real
areala

awk

awk基本语法

# 语法格式,注意awk后面的命令是单引号,如果是双引号的话里面带$符的会被识别成变量,有时会出现问题
awk [options] 'commands' filename
# options选项:
-F # 定义字段分隔符,默认的是以空格或者是制表符分隔

# commands分为三部分
BEGIN{} # 读所有行之前做的事情,只执行一次,可以省略
{} # 读所有行的时候做的事情
END{} # 读完所有行之后做的事情,只执行一次,可以省略

awk字段相关的内部变量

$0 # 记录的读取文件当前行的内容
awk '{print $0}' aa.txt # 将此文件的所有内容都读出来了

NR # 记录号,每处理完一条记录,记录号加1
awk '{print NR}' aa.txt

NF # 保存记录的字段数,$1,$2...$100
wk '{print NF}' aa.txt # 如果有分隔符,则会根据分隔符分隔后再计算每一行有多少个字段

FS # 就是-F,输入字段分隔符,默认空格
awk -F t '{print $0,NF}' aa.txt 

OFS # 输入字段分隔符,默认空格
awk -F : 'BEGIN{OFS="-"}{print$1,$3}' /etc/passwd # $1和$3字段会用"-"连接起来,默认是空格