Linux shell编程
0.概述
在shell编程中,很多时候实现目标的方式会有多种,根据个人的编程习惯表现形式也会多样。
1.变量
1.1环境变量
环境变量是操作系统运行环境的一些参数。在命令行使用printenv或env命令查看当前环境变量。
dhl@dhl:~$ env
SHELL=/bin/bash
PWD=/home/dhl
LOGNAME=dhl
XDG_SESSION_TYPE=tty
HOME=/home/dhl
LANG=zh_CN.UTF-8
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=00:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.avif=01;35:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:*~=00;90:*#=00;90:*.bak=00;90:*.crdownload=00;90:*.dpkg-dist=00;90:*.dpkg-new=00;90:*.dpkg-old=00;90:*.dpkg-tmp=00;90:*.old=00;90:*.orig=00;90:*.part=00;90:*.rej=00;90:*.rpmnew=00;90:*.rpmorig=00;90:*.rpmsave=00;90:*.swp=00;90:*.tmp=00;90:*.ucf-dist=00;90:*.ucf-new=00;90:*.ucf-old=00;90:
SSH_CONNECTION=192.168.32.1 49165 192.168.32.128 22
LESSCLOSE=/usr/bin/lesspipe %s %s
XDG_SESSION_CLASS=user
TERM=xterm
LESSOPEN=| /usr/bin/lesspipe %s
USER=dhl
DISPLAY=localhost:10.0
SHLVL=1
XDG_SESSION_ID=964
XDG_RUNTIME_DIR=/run/user/1000
SSH_CLIENT=192.168.32.1 49165 22
DEBUGINFOD_URLS=https://debuginfod.ubuntu.com
XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share:/usr/share:/var/lib/snapd/desktop
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/dhl/imx6ull/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
SSH_TTY=/dev/pts/0
_=/usr/bin/env
OLDPWD=/home/dhl
常用的环境变量:
PATH:命令的搜索路径,调用命令时系统会在相关的目录查找命令,多个目录用:分隔。
HOME:当前用户的家目录。
USER:当前用户。
SHELL:当前使用的 Shell 路径。
查看指定环境变量:
使用echo $VAR或者printf $VAR,答应指定的环境变量值,VAR为指定的变量名。
dhl@dhl:~$ echo $HOME
/home/dhl
dhl@dhl:~$ printf $HOME"\n"
/home/dhl
$HOME"\n"后面的"\n"表示换行,echo输出默认带有换行
添加环境变量:
- 添加临时环境变量:
使用export VAR=value添加环境变量,VAR为环境变量的名称,value为环境变量值。
dhl@dhl:~$ export NAME=dhl
dhl@dhl:~$ echo $NAME
dhl
- 添加永久环境变量:
修改环境变量:
使用export VAR=value也可以修改环境变量,VAR为环境变量的名称,value为环境变量值。
dhl@dhl:~$ export NAME=test
dhl@dhl:~$ ^C
dhl@dhl:~$ echo $NAME
test
删除环境变量:
使用环境变量:
1.2预定义变量
在Linux Shell脚本中,预定义了一些变量,先看如下程序和执行结果
#!/bin/bash
echo '$0:'$0
echo '$1:'$1
echo '${1}:'${1}
echo '${10}:'${10}
echo '$#:'$#
echo '$*:'$*
echo '$@:'$@
echo '$$:'$$
echo '$?:'$?
echo 'start $@'
for var in $@
do
echo $var
done
echo 'end $@'
echo 'start $*'
for var in $*
do
echo $var
done
echo 'end $*'
echo 'start "$@"'
for var in "$@"
do
echo $var
done
echo 'end "$@"'
echo 'start "$*"'
for var in "$*"
do
echo $var
done
echo 'end "$*"'
执行脚本
dhl@dhl:~/learn$ $(pwd)/test.sh 1 2 3 4 5 6 7 8 9 10
$0:/home/dhl/learn/test.sh
$1:1
${1}:1
${10}:10
$#:10
$*:1 2 3 4 5 6 7 8 9 10
$@:1 2 3 4 5 6 7 8 9 10
$$:2554695
$?:0
start $@
1
2
3
4
5
6
7
8
9
10
end $@
start $*
1
2
3
4
5
6
7
8
9
10
end $*
start "$@"
1
2
3
4
5
6
7
8
9
10
end "$@"
start "$*"
1 2 3 4 5 6 7 8 9 10
end "$*"
$0执行脚本的路径,不仅仅是脚本文件名称。$1-$9-${10}-${...}调用脚本传入的参数,$1是调用脚本传入的第一个参数,参数大于9时需要用{}访问,例如${10},当然$1也可以写成${1}。$#传入参数的个数。$*和$@是代表所有参数,$*和$@在大多时候一致,但在使用"时"$@"参数表有分隔符,"$*"将参数作为一个整体。$$是进程的PID。$?上一条指定的退出结果或函数的返回值。
另外注意"和'的区别,"括起来的字符串中含有变量是可以解引用的,'括起来的字符串多作为字符,不可解引用变量。"和'其他区别这里不介绍。
预定义变量中还有一个重要的变量$IFS,表示内部域分隔符(Internal Field Separator),通过如下程序运行可以看出$IFS默认值为空格、制表符(Tab)和换行符。在修改分隔符前要备份当前分隔符,方便后恢复分隔符。
#!/bin/bash
read a
printf "$IFS" | hexdump -C
OLD_IFS="$IFS"
IFS=','
printf "$IFS" | hexdump -C
for var in $a
do
echo $var
done
IFS=$OLD_IFS
printf "$IFS" | hexdump -C
执行脚本
dhl@dhl:~/learn$ ./ifs.sh
1,2,3
00000000 20 09 0a | ..|
00000003
00000000 2c |,|
00000001
1
2
3
00000000 20 09 0a | ..|
00000003
1.3自定义变量
变量的命名规则:
- 区分大小写
- 不能使用保留字和内置变量
- 由字母、数字和下划线组成,不能以数字开头
1.3.1 只读变量
1.3.2 局部变量
1.3.3 数组变量
2.分支结构
2.1 简单分支结构
简单分支结构可以使用if 条件1;then ... elif条件2;then ... else ... fi实现。
if和elif的条件可以使用test ... 和[ ... ]两种形式。
#!/bin/bash
read -p"输入两个数字:" num1 num2
function alertIsDigit(){
if [[ ! $1 =~ ^[-0-9]+$ ]];then
echo "$1不是有效数字"
exit
fi
}
alertIsDigit $num1
alertIsDigit $num2
if [ $num1 -gt $num2 ];then
echo "$num1大于$num2"
elif [ $num1 -lt $num2 ];then
echo "$num1小于$num2"
else
echo "$num1等于$num2"
fi
2.2 多路分支结构
#!/bin/bash
while true
do
read -p"输入成绩 : " score
if [[ ! $score =~ ^[-0-9]+$ ]] || [ $score -gt 100 -o $score -lt 0 ];then
echo "成绩无效($score)"
continue
fi
break
done
grade=$(($score/10))
case $grade in
9 | 10)grade=A;;
8)grade=B;;
7)grade=C;;
6)grade=D;;
*)grade=E
esac
echo "成绩为$grade"
3.循环
4.编程实践
4.1 冒泡排序
#!/bin/bash
read -p"输入数字数组: " -a a
function alertIsDigit(){
if [[ ! $1 =~ ^[-0-9]+$ ]];then
echo "第$2个数字($1)不是有效数字"
exit
fi
}
seq=1
for ele in ${a[@]}
do
alertIsDigit $ele $seq
((seq++))
done
echo "排序前: ${a[@]}"
for ((i=0;i<${#a[@]}-1;i++))
do
flag=0
for ((j=0;j<${#a[@]}-1-i;j++))
do
if [ ${a[j]} -gt ${a[j+1]} ];then
tmp=${a[j]}
a[j]=${a[j+1]}
a[j+1]=$tmp
flag=1
fi
done
if [ $flag -eq 0 ];then
break
fi
done
echo "排序后: ${a[@]}"

浙公网安备 33010602011771号