book_note for《Linux程序设计》chapter2 Shell编程

第2章 Shell编程

2.1 Bash脚本的建立与运行

Shell命令行

  • ;分隔命令
  • \表示换行补充

Shell程序是指放在一个文件中的一系列Linux命令和实用程序,执行时操作系统逐个解释和执行

Bash脚本的建立

echo "Mr.$USER, today is:"
echo &date "+%B%d%A"
echo "Wish you a lucky day!"
# 改变权限 for 可执行
chmod +x shell21 

# 执行程序
./shell21
bash shell21

2.2 Shell程序的位置参数与变量

位置参数

位置参数
  • 系统提供,将参数列表看做一个数组,访问: $N
  • $0为脚本文件的名字
cho $0
echo $1 
echo $*  # 所有参数 
echo $@  # 所有参数 
echo $#  # 参数个数
echo $$  # shell脚本进程ID号
echo $?  # 最近一次命令退出状态
echo $!  # 最后一次后台的ID号
  • 执行
$ bash 221 arg1 arg2
221
arg1
arg1 arg2
arg1 arg2
2
44286
0
  • 参数超过9个,则shift [N]
    • 表示将参数左移N个位置,然后继续使用数组下标来访问
$ cat 24 
echo $1
shift 2
echo $1
$ bash 24 1 2 3 4
1
3
设置位置参数的值
base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat 25
#! /bin/bash
filename=$1
set $(ls -il $filename)  # 将后面命令的输出设置为参数列表
ls -il $filename
inode=$1
right=$2
size=$6
echo "inode=\$1=$inode"
echo "right=\$2=$right"
echo "size=\$6=$size"

(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ bash 25 main.c 
2361026 -rw-rw-r-- 1 cola cola 0 23 20:50 main.c
inode=$1=2361026
right=$2=-rw-rw-r--
size=$6=0

环境变量与用户定义变量

指在在执行Shell脚本时的变量来源

  • 环境变量
$HOME  # 当前用户主目录
$PATH  # 搜索命令的目录
$PS1   # ?
$PS2 
$IFS   # 内部域分隔符
  • 用户变量: 数字、字母下划线,且大小写敏感

变量申明和赋值

申明变量
  • 变量默认是空字符串
  • 通过设置options来设定其类型

命令格式

declare [options] [name[=value]]
typeset [options] [name[=value]]

# options
-a  # array
-f  # function
-i  # integer
-r  # read only
-x  # 全局变量,可以被子进程访问
变量赋值
variable=value
  • 类型不同不能赋值
例如
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat 223
declare -i age=20
declare -rx OS=LINUX
var1=$OS
var2="abcd"
declare -i var3=10
echo $age
echo $OS
echo $var1
echo $var3
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ bash 223 
20
LINUX
LINUX
10
  • 变量申明及赋值
  • 默认赋值为字符串

变量引用和单双引号使用

引用
  • $var访问值
  • var=value可以用于修改变量
    • 第一次使用则会自动创建
单、双引号、反斜线的使用
$ declare -i age=20
$ echo $age
20
$ echo 'age==$age'
age==$age
$ echo "age==$age"
age==20
$ echo "age==\$age"
age==$age
  • '': 原封不动字符串
  • "": 对**$ \ `**作出解释

命令替换

两种命令替换方式

  • $(command)
$ echo "Infomation of 223: $(ls -l 223)"
Infomation of 223: -rw-rw-r-- 1 cola cola 120 24 17:28 223
  • 反引号会将其输出替换为命令的输出结果 -> 命令替换
$ ls -l 223
-rw-rw-r-- 1 cola cola 120 24 17:28 223
$ declare info=`ls -l 223`
$ echo $info
-rw-rw-r-- 1 cola cola 120 24 17:28 223

变量的输入

  • 从标注输入中输入一个变量
  • 换行结束
read [options] variable-list

# 常用选项如下
-a  # 词读入name数组中
-e  # 一整行读入一个变量,其余位NULL
-n  # echo输出命令字符后,光标任在同一行
-p prompt  # 从终端读入数据则显示prompt字符串
  • 注意

    • 赋值过多则剩余的全给最后一个变量
    • 赋值过少则,多余变量接受NULL
  • 以下Shell脚本,列出指定文件夹的文件信息,然后再回到工作路径

(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat 29
workspace=$PWD
echo "Enter direction path:"
read dir_name
cd $dir_name
ls -l
cd $PWD
pwd
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./29
Enter direction path:
../code1
总用量 32
-rw-rw-r-- 1 cola cola   64 23 20:34 221
-rw-rw-r-- 1 cola cola  120 24 17:28 223
-rw-rw-r-- 1 cola cola   24 23 20:42 24
-rw-rw-r-- 1 cola cola  212 23 20:57 25
-rwxrwxr-x 1 cola cola   89 24 22:43 29
-rw-rw-r-- 1 cola cola   60 23 20:25 cola22.cola
drwxrwxr-x 2 cola cola 4096 23 20:25 kk
-rw-rw-r-- 1 cola cola    0 23 20:50 main.c
-rwxrwxr-x 1 cola cola   77 23 20:10 shell21
/home/cola/cola_study/LinuxProgramming/code1

2.3 控制结构语句

bool运算

test [expression]
[ [expression] ]  # 外面的[]即表示 test
字符串比较
  • 以下均返回true
abcd = abcd
bcd != abcd
-n "cajd"  # 字符串不为空
-z ""  # 字符串为空
算数比较
exp1 -eq exp2

# more 双元
-ne
-gt
-ge
-lt
-le


# 一元
!exp
文件测试
-d dir
-e file_exist
-f filename
-r filename  # 可读
-s filename  # 文件长度不为0
-w filename  # 文件可写
-x filename  # 文件可执行

顺序结构的语句

if-then-elif-else-fi语句

  • 语句规则总结如下
if exp1
	then
	...
elif exp2
	then 
	...
elif exp3
	then 
	...
else
	...
fi
  • 使用案例: 删除某个文件,删除前做以判断,且是将文件压缩后送入回收站
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat 211.sh 
if test $# -eq 0
	then
	echo "Please enter specify file!"
else
	gzip $1  # 对文件进行压缩
	mv $1.gz $HOME/dustbin  # 移动到回收站
	echo "Moving right!"
fi
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./211.sh 25
Moving right!
  • 案例:输入文件则显示文件内容,文件夹则显示文件夹下的内容
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat 212.sh 
read file_or_dir
if [ -d $file_or_dir ]
	then
	ls -l $file_or_dir
elif [ -f $file_or_dir ]
	then
	cat $file_or_dir
else
	echo "Input error."
fi

for语句

  • python里面的类似
for variable [in argument-list]
do
	command-list
done
  • 使用
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat test.sh 
for filename in $*
do
	echo $filename
done

echo "Phase 2"

for item in abc deg g
do
	echo $item
done
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./test.sh a b c d e
a
b
c
d
e
Phase 2
abc
deg
g
  • 使用其他分隔符IFS(Internal Field Separator)
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat test.sh 
data="a, b, c, d"
IFS=", "
for item in $data
do
	echo $item
done
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./test.sh 
a
b
c
d
  • 列出某个文件夹下所有文件
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat test.sh 
trash_path="$HOME/.local/share/Trash/files/"
for filename in $(ls $trash_path)
do
	echo $filename
done
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./test.sh 
baboon0.png
baboon1.png
baboon.2.png
baboon2.png
baboon3.png
baboon.png
cola_1.c
  • 列出文件夹下所有模式的文件
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat test.sh 
for filename in $(ls *.sh)
do
	echo $filename
done
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./test.sh 
211.sh
212.sh
test.sh
  • 计算数列前n项和

    • todo

    • echo "N:"
      declare -i n
      declare -i num
      read n
      total=0.000
      an=1.000
      for ( (num=1; num<=$n; num++) ); do
              an=`echo "scale=3; 1.000/$num" | bc`
              total=`echo "scale=3; $total+%an" | bc`
      done
      echo $total
      
    • 上面为有bug的代码

while语句

while expression
do
	command-list
done
  • 输入直到条件成立
read input_sec
while [ $input_sec != "cola" ]
do
	echo "error!"
	read input_sec
done
echo "Input right"
  • 指定循环n
read input
declare -i times=$input
declare -i time=0
while test $time -lt $times
do
	read input
	echo "Input=$input"
	time=$time+1
done

utile语句

until expression
do
	command-list
done
  • expression一直为假则执行,直到其为真

case语句

  • 同嵌套的if语句类似的多路跳转功能
  • 替代条嵌套多层的if语句
case variable in 
	pattern1 ) ...
	;;
	pattern2 ) ...
	;;
	pattern3 ) ...
	;;
	pattern ) ...
	;;
esac

2.4 其他几个常用语句

break/continue

  • 同c

exit

  • 功能: 退出脚本
  • 不同的退出码代表不同的含义
exit n

# 退出码解释
n	含义
0 	成功
126	文件不可执行
127	命令未找到
>=128	出现一个信号

printf

  • 和C/C++输出类似
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ age=20
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ printf "name is %s\n%s\n" "Cola Cheng" "age=$age"
name is Cola Cheng
age=20
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ printf "%d %f %lf \n" 2 3.3 3.3
2 3.300000 3.300000 

2.5 数值处理

  • 变量值军事字符串格式存储
  • 要进行算数运算或者逻辑运算,得先将字符串转为整数,得到结果再转回字符串
  • 算数运算符和C/C++中相同

let命令

let expression-list
  • 感觉上,就像是有一个简单的符号计算器
  • 内部变量不需要使用$
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat test.sh 
z=4
let x=3 y=4
let t=x*y*z "t2=x**y"
echo $t $t2
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./test.sh 
48 81

$((expression))$扩展

  • 运算结果直接替换
  • 用于命令行的参数替换
  • Shell必须将字符串转为整数 if 使用的变量不是正的整数(a=30是真的整数,a=2.2不是)
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat test.sh 
echo "Inpute you age:"
read age
echo Next $((100-age)) years.
echo $((age*10))

content=$(( $(wc -l < test.sh)*2+1  ))
echo $content
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./test.sh 
Inpute you age:
21
Next 79 years.
210
15

expr 命令

  • 将参数作为表达式求值
expr args

# 常用
x = `expr $x+1`
  • 使用
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat test.sh 
a1=4
a1=$( expr $a1 + 1 )
echo $a1
a1=$( expr $a1 + 3 \* 3)
echo $a1
echo $( expr $a1 / 4 )
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./test.sh 
5
14
3
  • 注意:
    • 表达式中所有符号必须分割开,不然会被解析为字符串!
    • 乘法需要使用\*

2.6 数组

数组基本操作

  • 定义、下标访问、计算长度、删除元素
# array define
arr=(ab cd ef)

# indicate array
echo ${arr[1]}

# length of array
echo ${#arr}  # len of arr[0] (byte)
echo ${#arr[0]}  # same 
echo ${#arr[*]}  # 数组元素个数


# delete array
unset arr[0]
unset arr

数组子串操作

子串访问
a=(zero one two three four five)
echo ${a[@]:1:3}
echo ${a[@]:2}
echo ${a[@]::3}
删除子串
# 删除子串
echo ${a[@]#f*r}  # 删除左边开始最短匹配
echo ${a[@]#f*r}  # 删除左边开始最长匹配
echo ${a[@]%f*r}  # 删除右边开始最短匹配
echo ${a[@]%%f*r}  # 删除右边开始最短匹配
子串替换

2.7 函数

function_name() {
	command-list
}

参数传递&局部变量定义&返回值

  • 变量位置参数$*、$@等将会替换为函数的参数(函数局部有效)
  • local关键词可以在Shell函数中声明局部变量
  • 同名变量则局部覆盖全局
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ cat test.sh 
func() {
	# 使用位置参数
	for item in $*
	do
		echo $item
	done
	
	# 定义局部变量
	local var=abcd
	echo $var

	# 返回值
	return 1 
}

if func cola ysc 
	then
	echo "func return true"
fi
(base) cola@cola-CM:~/cola_study/LinuxProgramming/code1$ ./test.sh 
cola
ysc
abcd
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值