Linux 学习之路(六):bash脚本编写

本文介绍了Linux bash脚本中的整数测试、文件测试、位置变量和特殊变量的使用。通过示例展示了如何进行整数比较、文件权限检查以及使用特殊变量 `$?`, `$#`, `$*`, `$@`。还涵盖了`sed`命令的基本用法,包括删除、替换和追加行的操作,并给出了一些实际应用的练习案例。" 111420883,10293793,Python实现小波分析:时间序列周期揭示,"['Python编程', '数据分析', '小波理论', '时间序列分析']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

bash脚本编程:整数测试及特殊变量

exit:退出脚本

exit #

如果脚本没有明确定义退出状态码,那么,最后执行的一条命令的退出码即为脚本的退出状态码。

bash中常用的条件测试有三种:

测试方法:

命令测试法 [ expression ]

关键字测试法 [[ expression ]]

test expression

整数测试:

​ -gt,-le,-ne,-eq,-ge,-lt

INT1=63

INT2=77

[ $INT1 -eq $INT2 ]

[[ $INT1 -eq $INT2 ]]

test $INT1 -eq $INT2

文件测试:

-e FILE 路径:测试文件是否存在

-f FILE 路径:测试文件是否为普通文件

-d FILE 路径:测试指定路径是否为目录

-r FILE:测试当前用户对指定文件是否有读权限;

-w:是否有写权限

-x:是否有执行权限

\[ -e /etc/inittab ]

多分支的if语句:

if 判断条件1; then

	statement1

	...

elif 判断条件2; then

	statement2

	...

else

	statement4

	...

fi

测试脚本是否有语法错误:

bash -n 脚本名称

bash -x 脚本:单步执行

练习:写一个脚本

给定一个文件:

如果是一个普通文件,就显示之

如果是一个目录,亦显示之

否则,此为无法识别文件

#!/bin/bash
FILE=/etc/rc.d/rc.sysinit
if [ ! -e $FILE ]; then
	echo "No such file"
	exit 6
fi
if [ -f $FILE ];then
	echo "Common file."
elif [ -d $FILE ];then
	echo "Directory"
else
	echo "Unkown"
fi	

练习:写一脚本

能接受一个参数(文件路径)

判定:此参数如果是一个存在的文件,就显示“OK”

$1表示脚本第一个参数

#!/bin/bash
if [ $# -lt 1 ]; then
	echo "Usage: ./filetest3.sh ARG1 [ARG2...] "
	exit
fi	
if [ -e $1 ];then
	echo "OK"
else
	echo "No such file."
fi	
位置变量:

​ $1,$2,…

​ shift 轮换/轮替

#!/bin/bash
echo $1
shift 2
echo $1
shift 2
echo $1

练习:写一个脚本

给脚本传递两个参数(整数):

显示此两者之和,之积

#!/bin/bash
if [ $# -lt 2 ];then
	echo "Usage:cacl.sh ARG1 ARG2"
	exit 8
fi
echo "The sum is: $[$1+$2]."
echo "The prod is: $[$1*$2]"
特殊变量:

$?

$# 参数的个数

$* 参数列表

$@ 参数列表

sed命令(stream Editor):

流编辑器

基本用法:

行编辑器(全屏编辑器:vi)

模式空间

默认不编辑源文件,仅对模式空间中的数据做处理;而后,处理结束后,将模式空间打印

sed 'AddressCommand' file ...

​ -n:静默模式,不再默认显示模式空间中的内容

​ -i:直接修改原文件

​ -e SCRIPT -e SCRIPT:可以同时执行多个脚本

​ -f /PATH/TO/SED_SCRIPT:

sed -f /path/to/scripts file

​ -r: 使用扩展正则表达式

Address:

1.StartLine,EndLine

​ 比如1,100

​ $:最后一行

​ $-1:倒数第二行

2./RegExp/

​ /^root/

3./pattern1/,/pattern2/

​ 第一次被pattern1匹配到的行开始,至第一次被pattern2匹配到的行结束中间的所有行

4.LineNumber

​ 指定的行

5.StartLine,+N

​ 从startline开始,向后的N行;

Command:

​ d:删除符合条件的行;

sed '1,2d' /etc/fstab
sed '/oot/d' /etc/fstab
sed '1,+2d' /etc/fstab 删除3行
sed '1d' /etc/fstab 只删除第一行

​ p:显示符合条件的行;

sed -n '/^\//p' /etc/fstab 显示以斜线开头的行

追加一行:

sed '/^\//a \# hello world' /etc/fstab

​ a \string:在指定的行后面追加新行,内容为string

​ i \string:在指定的行前面添加新行,内容为string

​ r FILE : 将指定的文件的内容添加至符合条件的行处

​ w FILE:将指定范围内的内容另存至指定的文件中

​ s/pattern/string/ 修饰符: 查找并替换,默认只替换每行中第一次被模式匹配到的串

​ 加修饰符

​ g:全局替换

​ i:忽略字符大小写

​ s///?###,s@@@

​ \(\),\1,\2

把行首#换成/

sed 's/^\//#/' /etc/fstab
l...e:like...liker
	  love...lover	
sed 's#l...e#&r#g' sed.txt
后向引用
sed 's#\(l...e\)#\1r#g' sed.txt
like...Like
love...Love
只需用到前面匹配内容的一部分时使用后向引用
sed 's#l\(..e\)#L\1#g' sed.txt

sed命令删除行首空白字符:(锚定行首,查找替换空格为什么都没有)

history | sed 's#^[[:space:]]*##g'

取出路径的父目录

/var/log

sed练习:

1.删除/etc/grub.conf文件中行首的空白符;

sed -r ‘s@1+@@g’ /etc/grub.conf

2.替换/etc/inittab文件中"id:3:initdefault:"一行中的数字为5

sed ‘s@\(id:\)[0-9]\(:initdefault:\)@\15\2@g’ /etc/inittab

3.删除/etc/inittab文件中的空白行

sed ‘/^$/d’ /etc/inittab

4.删除/etc/inittab文件中开头的#号

sed ‘s@^#@@g’ /etc/inittab

5.删除某文件中开头的#号及后面的空白字符,但要求#号后面必须有空白字符

sed -r ‘s@^#[[:space:]]+@@g’ /etc/inittab

6.删除某文件中以空白字符后面跟#类的行中的开头的空白字符及#

sed -r ‘s@2+#@@g’ /etc/inittab

7.取出一个文件路径的目录名称

echo “/etc/rc.d” | sed -r ‘s@(/.*/)[/]+/?@\1@g’

基名:

echo “/etc/rc.d” | sed -r ‘s@/.*/([/]+)/?@\1@g’

#abc

# hello world

​ # hi world

我的解答:

1。
[root@localhost /]# sed 's#^[[:space:]]*##g' /etc/grub.conf
1234567
2.
sed 's#(?<=\:)[^\s\:]+(?=\:)#5#' /etc/inittab 存疑
3.
[root@localhost /]# sed '/^$/d' /etc/split.txt
#abc
# hello world
   #hi world
4.
[root@localhost /]# sed 's/\#*//g' /etc/split.txt

abc
 hello world
   hi world
5.
[root@localhost /]# sed 's/\#[[:space:]]//g' /etc/split.txt

#abc
hello world
   #hi world
6.
[root@localhost /]# sed 's/.*[[:space:]]\#//g' /etc/split.txt

#abc
# hello world
hi world
7.
字符串测试:

==

!=:测试是否不等,不等为真,等为假

>

<

-n string:测试指定字符串是否为空,空为真,不空为假

-s string:测试指定字符串是否不空,不空为真,空为假

传递一个用户名参数给脚本,判断此用户的用户名跟其基本组的组名是否一致,并将结果显示出来。

if [ `id -n -u $1` == ` id -n -g $1` ];then

​ echo “Yiyang”

else

​ echo “Buyiyang”

fi

传递一个参数(单字符就行)给脚本,如参数为q,就退出脚本;否则就显示用户的参数:

#!/bin/bash

if [ $1 = ‘q’];then

​ echo “Quiting…”

​ exit 1

elif [ $1 = ‘Q’ ];then

​ echo “Quiting…”

​ exit 2

fi

bc 使用scale=2可以保留精度

echo "scale=2;111/22;" |bc

bc <<< "scale=2;111/22;"

写一个脚本:

给脚本传递三个整数,判断其中的最大数和最小数,并显示出来

MAX=0

MAX -eq $1

MAX=$1

MAX -lt $2

MAX=$2

传递3个参数给脚本,参数均为用户名,将此些用户的账号信息提取出来后放置于/tmp/testusers.txt文件中,并要求每一行行首有行号。

echo “1 $LINE” >> /tmp/testusers

循环:进入条件,退出条件

for

while

until

for 变量 in 列表; do

​ 循环体

done

如何生成列表:

{1…100}

`seq [起始数 [步进长度]] 结束数` 注:[]可省

declare -i SUM=0 把变量声明为整型

从1加到100
#!/bin/bash
declare -i SUM=0
for I in {1..100}; do
	let SUM=$[$SUM+$I]
done
echo "The sum is: $SUM"

取出行中每一行并问好。

LINES=`wc -l /etc/passwd | cut -d' ' -f1`
for I in `seq 1 $LINES`; do
	echo "Hello,`head -n $I /etc/passwd | tail -1 | cut -d: -f1^`"
done	

case语句及脚本选项进阶

case语句:选择结构

case SWITCH in

value1)

statement

...

;;

value2)

statement

...

;;

*)

statement

...

;;

esac

举个栗子:

#!/bin/bash
case $1 in
[0-9])
        echo "A digit." ;;
[a-z])
        echo "Lower." ;;
[A-Z])
        echo "Upper." ;;
*)
        echo "others." ;;
esac      
#检查语法
[root@localhost jiaoben]# bash -n case.sh
[root@localhost jiaoben]# chmod +x case.sh
[root@localhost jiaoben]# ./case.sh a
Lower.

只接受参数start,stop,restart,status其中之一

#!/bin/bash
case $1 in
'start')
        echo "start server......" ;;
'stop') 
        echo "stop server......" ;;
'restart')            
        echo "restart server......." ;;
'status')
        echo "running......" ;;
*)
        echo "`basename $0` {start|stop|restart|status}" ;;
esac    
[root@localhost jiaoben]# ./service.sh st
service.sh {start|stop|restart|status}

写一个脚本。可以接受选项及参数,而后能获取每一个选项,及选项的参数;并能根据选项及参数做出特定的操作,比如

adminusers.sh --add tom,jerry --del tom,blair -v|–verbose -h|–help

添加用户成功即显示详细信息

#!/bin/bash
DEBUG=0

case $1 in
-v|--verbose)   
        DEBUG=1 ;;
esac
useradd tom &> /dev/null
[ $DEBUG -eq 1 ] && echo "Add user tom finished."
[root@localhost jiaoben]# ./addusers.sh -v
Add user tom finished.

#!/bin/bash
DEBUG=0
ADD=0
DEL=0

case $1 in
-v|--verbose)
        DEBUG=1
        shift ;;
-h|--help)
        echo "Usage:`basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
        exit 0
        ;;  
--add)
        ADD=1
        USERS=$2
        shift 2
        ;;  
--del)
        DEL=1
        USERS=$2
        shift 2
        ;;  
*)
        echo "Usage :` basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
        exit 7
        ;;  
esac

删除和添加用户可以同时使用
[root@localhost jiaoben]# ./adminusers1.sh --add tom,jerry,natasha --del tom
[root@localhost jiaoben]# ./adminusers1.sh -v --add tom,jerry,natasha --del tom
Add user tom finished.
jerry exists.
natasha exists.
Delete tom finished.

adminusers1.sh
#!/bin/bash
DEBUG=0
ADD=0
DEL=0

for I in `seq 1 $#`;do
if [ $# -gt 0 ];then    
case $1 in
-v|--verbose)
        DEBUG=1
        shift ;;
-h|--help)
        echo "Usage:`basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
        exit 0
        ;;  
--add)
        ADD=1
        ADDUSERS=$2
        shift 2
        ;;  
--del)
        DEL=1
        DELUSERS=$2
        shift 2
        ;;  
*)
        echo "Usage :` basename $0` --add USER_LIST --del USER_LIST -v|--verbose -h|--help"
        exit 7
;;
esac
fi
done

if [ $ADD -eq 1 ]; then
        for USER in `echo $ADDUSERS | sed 's@,@ @g'`;do
               if id $USER &> /dev/null; then
                        [ $DEBUG -eq 1 ] && echo "$USER exists."
                else
                        useradd $USER
                        [ $DEBUG -eq 1 ] && echo "Add user $USER finished."
                fi
        done
fi

if [ $DEL -eq 1 ];then
        for USER in `echo $DELUSERS | sed 's@,@ @g'`;do
               if id $USER &> /dev/null; then
                       userdel -r $USER
                       [ $DEBUG -eq 1 ] && echo "Delete $USER finished."
                else
                        [ $DEBUG -eq 1 ] && echo "$USER not exist"
                fi
        done
fi
#正常退出与非正常退出
[root@localhost jiaoben]# ./adminusers1.sh --help
Usage:adminusers1.sh --add USER_LIST --del USER_LIST -v|--verbose -h|--help
[root@localhost jiaoben]# echo $?
0
[root@localhost jiaoben]# ./adminusers1.sh --abc
Usage :adminusers1.sh --add USER_LIST --del USER_LIST -v|--verbose -h|--help
[root@localhost jiaoben]# echo $?
7

练习:写一个脚本showlogged.sh,其用法格式为

showlogged.sh -v -c -h| --help

其中,-h选项只能单独使用,用于显示帮助信息;-c选项时,显示当前系统上登录的所有用户数;如果同时使用了-v选项,则既显示同时登录的用户数,又显示登录的用户的相关信息。

#!/bin/bash
declare -i SHOWNUM=0
declare -i SHOWUSERS=0
for I in `seq 1 $#`;do
        if [ $# -gt 0  ];then
                case $1 in
                        -h|--help)
                                echo "Usage:`basename $0` -v|--verbose -h|--help -c|--count"
                                exit 0
                                ;;  
                        -v|--verbose)
                                let SHOWUSERS=1
                                shift
                                ;;  
                        -c|--count)
                                let SHOWNUM=1
                                shift
                                ;;  
                        *)  
                                echo "Usage:`basename $0` -v|--verbose -h|--help -c|--count"
                                exit 8
                                ;;  
                esac
        fi  
done
if [ $SHOWNUM -eq 1 ];then
        echo "Logged users:`who | wc -l`."
fi
if [ $SHOWUSERS -eq 1 ];then
        echo "They are:"
        who
fi
[root@localhost jiaoben]# vim showlogged.sh
[root@localhost jiaoben]# chmod +x showlogged.sh
[root@localhost jiaoben]# ./showlogged.sh -h
Usage:showlogged.sh -v|--verbose -h|--help -c|--count
[root@localhost jiaoben]# echo $?
0
[root@localhost jiaoben]# ./showlogged.sh -v
./showlogged.sh: 第 29 行:[: 缺少 `]'
[root@localhost jiaoben]# vim showlogged.sh
[root@localhost jiaoben]# ./showlogged.sh -v
They are:
root     tty1         2018-10-20 10:45
root     pts/0        2018-10-21 09:18 (192.168.83.1)
root     pts/1        2018-10-21 13:25 (192.168.83.1)

  1. [:space:] ↩︎

  2. [:space:] ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值