Shell相关命令

一、Shell的输入输出

1.1 输出 -- echo

#!/bin/bash 

#echo 的作用是将后边的内容打印到终端 自带换行
echo hello world
V1=nihao
echo ${V1}beijing

# -n 选项 表示不带换行符
V2="hello world"
echo -n $V2

# -e 选项 表示识别字符串中的转义字符 如换行符 \n
V3="nihao\nbeijing"
echo -e $V3

结果:
hello world
nihaobeijing
hello worldnihao
beijing

1.2 输入 -- read

阻塞等待在终端获取一个字符串 赋值给变量V1

#!/bin/bash 

#阻塞等待在终端获取一个字符 赋值给变量V1
read V1
echo $V1
结果:
hello world ni hao
hello world ni hao

也可以一次输入多个字符串 输入时以空格分隔

如果一次read多个时 输入的内容本身包含空格 这种方式会有问题

不推荐一次输入多行

read V2 V3
echo V1=$V2
echo V2=$V3
结果:
hello world ni hao # 有空格就表示赋了一个值,剩下的赋给最后一个
V1=hello					 # 想给V1赋值hello world 
V2=world ni hao    # 因为有空格就默认剩下的赋值给下一个参数了

一般使用下面的用法,单个read 以回车分隔

#!/bin/bash 

read V1
read V2
echo V1=$V1
echo V2=$V2 
结果:
hello world
ni hao
V1=hello world
V2=ni hao

-p "string" 表示给输入添加提示信息

#!/bin/bash 

read -p "输入一个字符串 >> " STRING
echo STRING=$STRING 
结果:
输入一个字符串 >> hello world
STRING=hello world

-a 表示输入一个数组 输入时以空格分隔

#!/bin/bash 

read -a ARR
echo ${ARR[@]}
echo ${#ARR[*]}
结果:
aa bb cc dd
aa bb cc dd
4

-n 4 表示最多读取4个字符 如果输入够4个字符 即使不敲回车 也会继续往下执行

#!/bin/bash 

read -n 4 VALUE
echo $VALUE
结果:
sacesace

-t 5 表示最多等待5秒 5秒没有输入就继续执行 表示赋值为空

#!/bin/bash 
read -t 5 V1
echo $V1

-s 表示取消输入的回显

#!/bin/bash 
read -p "请输入信息: " -s V1
echo $V1
结果:
请输入信息: 1234567

#!/bin/bash 

read -p "请输入你要下载的软件:" -n 20 -t 10 V1
sudo apt-get install $V1
$V1 

二、Shell中的运算

Shell本身是用来执行命令的,不是用来做复杂运算的,如需要复杂运算,可以在Shell脚本里调用C程序完成

但是,一些场景中用到简单运算,例如计数变量自增,用C语言太麻烦,就可以用Shell编程算数运算

Shell如果不做特殊处理,所有运算符都会将变量的值当作字符串来处理

Shell不支持浮点数运算

shell中做算数运算的方式有4中:

(())

$[]

let

expr

上述四种运算方式,执行的效率是依次递减的。

一定要保证自己会用一种 推荐掌握 (()) 其他的作为了解

2.1 (())

((表达式))

((表达式1,表达式2,表达式3,... ,表达式n))

每个表达式都会参与运算,最后一个表达式的结果,就是整个(())运算符的结果

注意:

1.(())内部引用变量的值的时候 $ 可加可不加

2.(())内部运算符前后的空格 可加可不加

3.如果想引用整个(())表达式的结果 需要在前面加 $ -->$((表达式))

4.(())可以做复杂的算术运算:如:++ -- for循环等

for((i=0;i<5;i++))

do

done

#!/bin/bash 

V1=10
V2=20
echo $((V1+V2))
echo $(($V1+$V2))
echo $(($V1 + $V2))
echo $((V1 + V2))
echo "------------------------------------------"

V3=100
((V3++))  #这种自增自减时 变量前 不可以加$
echo $V3 
echo "------------------------------------------"

V4=10
V5=20
V6=30
RET=$((++V4,++V5,++V6))
echo $RET $V4 $V5 $V6
echo "------------------------------------------"

#循环执行5次ls
for((i=0;i<5;i++))
do 
	echo ni hao
done
echo "------------------------------------------"
结果:
30
30
30
30
------------------------------------------
101
------------------------------------------
31 11 21 31
------------------------------------------
ni hao
ni hao
ni hao
ni hao
ni hao
------------------------------------------

三、Shell中的if...else语句

if [ 表达式1 ]   #if 和 [] 之间,[] 和表达式之间必须要有空格
then
  代码块1
elif [ 表达式2 ] #if 和 [] 之间,[] 和表达式之间必须要有空格
then
  代码块2
else						#else分支没有then
  其他分支
fi

3.1 对字符串的判断

注意:判断字符串时,最好用双引号把字符串引起来,否则,一旦字符串中有空格,就会报语法错误

-z 判断字符串是否为空

-n 判断字符串是否非空

==或= 判断字符串是否相等

!= 判断字符串是否不等

\> 判断字符串是否 前面大于后面

\< 判断字符串是否 前面小于后面

拓展:

> 和 >> 是输出重定向符

< 和 << 是输入重定向符

> 覆盖写

< 追加写

例:

#!/bin/bash 

read -p "input str1 >>" str1
read -p "input str2 >>" str2 

if [ -z "$str1" ]
then
	echo "str1空"
else
	echo "str1非空"
fi
echo "----------------------------------------"

if [ -n "$str2" ]
then
	echo "str2非空"
fi
echo "----------------------------------------"

#判断字符串是否相等 用==或=都可以
if [ "str1" == "str2" ]
then
	echo "=="
else
	if [ "str1" \> "str2" ]
	then
		echo "str1 > str2"
	else
		echo "str1 < str2"
	fi
fi
echo "----------------------------------------"
结果:
input str1 >>hello
input str2 >>hallo
str1非空
----------------------------------------
str2非空
----------------------------------------
str1 < str2
----------------------------------------

3.2 将字符串按整数的方式比较

-gt 大于 great then

-lt 小于 less then

-eq 等于 equal

-ge 大于等于 great equal

-le 小于等于 less equal

-ne 不等于 not equal

逻辑运算符

-a 逻辑与 && and

-o 逻辑或 || or

! 逻辑非 !

关于逻辑运算符:

在两个[]之间要用 &&

在一个[]内部要用 -a

#!/bin/bash
read -p "input V1 >>" V1
read -p "input V2 >>" V2

if [ "$V1" -eq "$V2" ]
then
	echo "V1==V2"
else
	if [ "$V1" -gt "$V2" ]
	then
		echo "$V1 > $V2"
	else
		echo "$V1 < $V2"
	fi
fi

echo "--------------------------------"

#if [ "$v1" -gt 0 && "$v2" -gt 0 ]     #错误
#if [ "$v1" -gt 0 ] -a [ "$v2" -gt 0 ] #错误
#if [ "$v1" -gt 0 ] && [ "$v2" -gt 0 ] #正确
if [ "$V1" -gt 0 -a "$V2" -gt 0 ]
then
	echo "yes"
else
	echo "no"
fi
结果:
input V1 >>32
input V2 >>23
32 > 23
--------------------------------
yes

#!/bin/bash 
read -p "请输入你的成绩 >> " S
if [ "$S" -ge 90 -a "$S" -le 100 ]
then 
	echo "A"
elif [ "$S" -ge 80 ] && [ "$S" -lt 90 ]
then
	echo "B"
elif [ "$S" -ge 70 -a "$S" -lt 80 ]
then 
	echo "C"
elif [ "$S" -ge 60 -a "$S" -lt 70 ]
then 
	echo "D"
else
	echo "不及格"
fi
结果:
请输入你的成绩 >> 100
A

3.3 判断文件的类型

-e 判断文件是否存在 存在为真 不存在为假

-s 判断文件是否存在 且判断文件是否为非空 非空真 空假

-b 判断文件是否存在 且判断文件是否为块设备文件

-S(大写) 判断文件是否存在 且判断文件是否为套接字文件

-p 判断文件是否存在 且判断文件是否为管道文件

-f 判断文件是否存在 且判断文件是否为普通文件

-L(大写) 判断文件是否存在 且判断文件是否为符号链接文件

-c 判断文件是否存在 且判断文件是否为字符设备文件

-d 判断文件是否存在 且判断文件是否为目录文件

注意事项

1.虽然 -s -b 等都具备判断文件是否存在的能力

但是我们使用时一般都是先用 -e 判断是否存在 存在的情况下再判断类型

否则 判断结果为假时 没法区分是类型不匹配导致的假 还是不存在导致的假

2.在判断链接文件时,他既满足链接文件的类型 也满足被链接文件的类型

所以一般判断类型时 我们都现判断链接文件

#!/bin/bash 
read -p "请输入一个文件 >> " FILE

if [ -e $FILE ]
then 
	echo "文件存在"
	if [ -s $FILE ]
	then
		echo "非空"
	else
		echo "空"
	fi
else
	echo "文件不存在"
fi
结果:
请输入一个文件 >> a.c
文件存在
非空
#!/bin/bash 
read -p "请输入一个文件名 >> " FILE

if [ -e $FILE ]
then
	if [ -L $FILE ]
	then
		echo "链接文件"
	elif [ -f $FILE ]
	then 
		echo "普通文件"
	elif [ -d $FILE ]
	then 
		echo "目录文件"
	else
		echo "其他文件"
	fi
else
	echo "文件不存在"
fi
结果:
请输入一个文件名 >> a.c
普通文件

3.4 判断文件权限

-r 判断文件是否存在 且判断文件是否有读权限

-w 判断文件是否存在 且判断文件是否有写权限

-x 判断文件是否存在 且判断文件是否有执行权限

注意:谁来执行脚本,判断的就是文件对谁的权限

#!/bin/bash 
read -p "input a file >> " FILE
if [ -e $FILE ]
then
	if [ -r $FILE ]
	then
		echo "有读权限"
	else
		echo "没有读权限"
	fi 
else
	echo "文件不存在"
fi
结果:
input a file >> a.c
有读权限

3.5 判断文件的时间戳

文件的时间戳:文件最后一次被修改的时间

-nt (new than) 判断两个文件的时间戳 前面的是否比后面的新

-ot (old than) 判断两个文件的时间戳 前面的是否比后面的旧

注意:距离现在越近的越新

#!/bin/bash 
read -p "input file >> " FILE1
read -p "input file >> " FILE2
if [ $FILE1 -nt $FILE2 ]
then 
	echo "1new"
else
	echo "2new"
fi
结果:
input file >> 04	
input file >> 02	
2new

3.6 判断文件的inode号是否相同

只有同一组的硬链接文件 inode 号才相同

-ef 相同为真 不同为假

#!/bin/bash 
read -p "input file >> " FILE1
read -p "input file >> " FILE2
if [ $FILE1 -ef $FILE2 ]
then 
	echo "相同"
else
	echo "不同"
fi
结果:
input file >> a.c
input file >> link
相同

#!/bin/bash 
read -p "input a file >> " FILE
if [ -e $FILE ]
then
	if [ -f $FILE ]
	then
		if [ -w $FILE ]
		then
			echo "hello world" >> $FILE
			tail -n 5 $FILE
		else
			echo "没有写权限"
		fi
	else
		echo "不是普通文件"
	fi
else
	echo "文件不存在"
fi
结果:
input a file >> a.c
hello
hello
hello
hello world
hello world

四、shell中的 case..in 语句

4.1 格式

case $变量 in
    选项1)
        分支1
        ;;
    选项2)
        分支2
        ;;
    ...
    *)
        其他分支
        ;;
esac

注意:

1. case后面一定写的是变量的值 ($变量)

2.每个选项中的字符串就是case后面变量所有可能的结果

3. *选项 表示其他分支 相当于 switch..case 语句的 default分支 如果不需要 也可以不写

4.2 关于case..in语句的选项

"hello" 匹配hello

"aa"|"bb"|"cc" 匹配 aa 或者 bb 或者 cc

[0-9] 匹配0-9中的任意一个字符

[a-z] 匹配a-z中的任意一个字符

[abc] 匹配abc中的任意一个字符

#!/bin/bash 
read -p "input a string >> " STR

case "$STR" in 
	"hello")
		echo "is hello"
		;;
	"aa"|"bb"|"cc")
		echo "is aa bb cc "
		;;
	hqyj[xmn])
		echo "hqyj "
		;;
	file[abc][0-9])
		echo "file"
		;;
	*)
		echo "other"
		;;
esac
结果:
input a string >> hello
is hello

思考:

如何能实现不管用户如何输入 y 后者 yes 都认为确认,否则是取消

y Y yes YES YeS yEs YEs ......

#!/bin/bash 
read -p "您要删除吗? [Y/n] " C
case $C in
	[Yy][Ee][Ss]|[Yy])
		echo "yes"
		;;
	*)
		echo "No"
		;;
esac
结果:
您要删除吗? [Y/n] y
yes

五、shell中的 while 循环

5.1 格式

while [ 表达式 ]
do
    循环体
done

其中 表达式的用法 和 if..else 语句的表达式用法一模一样

#!/bin/bash 

i=1
while [ $i -le 100 ]
do
	sum=$((sum+i))
	((i++))
done
echo $sum #5050
结果:
5050

5.2 死循环

while [ 1 ]
do
    循环体
done

while ((1))
do
    循环体
done

while true
do
    循环体
done

例:使用while循环每秒打印一次系统时间

#!/bin/bash 
while ((1))
do
	date
	sleep 1
done
结果:
2024年 09月 14日 星期六 20:21:50 CST
2024年 09月 14日 星期六 20:21:51 CST
2024年 09月 14日 星期六 20:21:52 CST
^C

六、shell中的for循环

6.1 C风格的for循环

for ((i=0;i<5;i++))
do
  echo $i
done

6.2 shell中特有的for循环

for 变量 in 单词列表
do 
  循环体
done

单词列表:

1.单词列表使用 空格 分割的,执行时 会自动将单词列表中的单词 逐个的赋值给变量,每赋值一次 循环执行一次

2.如果单词列表是连续的 可以使用 {start..end} 如 {1..100},也可以使用序列的写法 `seq 1 10`

如果有间隔 也可以使用 `seq 1 2 10` 表示 从1 到10 跨度为2 取值

3.单词列表也可以是命令的结果 (如 $(ls) 或者 `ls` )

4.省略in和单词列表的for循环,这种情况下 单词列表来自于执行脚本时命令行传的参数

#!/bin/bash 

for i in aa "bb" 'hello'
do
	echo hqyj-$i
done
echo "------------------------------"

for i in {1..10}
do
	echo "hello world $i"
done
echo "------------------------------"

for i in `seq 1 2 10`
do
	echo "hqyj $i"
done
echo "------------------------------"
结果:
hqyj-aa
hqyj-bb
hqyj-hello
------------------------------
hello world 1
hello world 2
hello world 3
hello world 4
hello world 5
hello world 6
hello world 7
hello world 8
hello world 9
hello world 10
------------------------------
hqyj 1
hqyj 3
hqyj 5
hqyj 7
hqyj 9
------------------------------

将当前目录下的所有普通文件权限修改为 0660

#!/bin/bash 
for i in `ls`
do 
	if [ -f $i ]
	then
		chmod 0660 $i
	fi
done
结果:
-rw-rw---- 1 linux linux 273 9月  14 20:30 28for.sh
-rw-rw---- 1 linux linux  77 9月  14 20:34 29for.sh
-rw-rw---- 1 linux linux  66 9月  14 20:05 a.c
lrwxrwxrwx 1 linux linux   3 9月  14 14:05 link -> a.c

#省略in和单词列表的for循环

#!/bin/bash 
for i
do
	echo $i
done
结果:
hello
world

七、shell中的break和continue

break 结束本层的循环

continue 结束本层的本次循环

break n n是一个数字 表示结束n层的循环

continue n n是一个数字 表示结束n层的本次循环

#!/bin/bash 

for((i=1;i<=5;i++))
do
	for((j=1;j<=5;j++))
	do
		if [ $j -eq 3 ]
		then
			#如果记不清 把此处注释打开 看现象对比就明白了
			#break
			#continue
			#break 2
			continue 2
		fi
		echo $i--$j
	done
done
结果:
1--1
1--2
2--1
2--2
3--1
3--2
4--1
4--2
5--1
5--2

八、shell中select..in语句

select 变量 in 单词列表
do
  语句
done

功能:将单词列表转换成一个可供用户选择的列表,方便用户操作

用户选择时 只能写编号 不能写单词

#!/bin/bash
select i in beijing shanghai tianjin
do
  echo 我选择的城市是$i
done

结果:

其中 #? 是提示符 可以通过修改环境变量 PS3 来自己指定

export PS3="input>>"

一般 select..in 语句会配合着 case..in 语句使用,供用户选择:

#!/bin/bash 

select i in beijing shanghai tianjin
do
	case $i in
		beijing)
			echo "人多"
			;;
		shanghai)
			echo "钱多"
			;;
		tianjin)
			echo "大爷多"
			;;
	esac
	break
done

九、shell中的函数

#function可以不写 但是为了方便阅读代码 建议写上
function 函数名(){
函数体
}

注意:

1.shell中的函数是没有参数列表

2.shell中函数没有返回值类型

3.shell中的函数使用关键字function声明,function也可以不写,但是()必须写

4.shell中的函数名也要符合命名规范

5.shell中函数如果不被调用 也不会执行

9.2 函数的调用

没有参数: 函数名

有参数: 函数名 参数1 参数2 ... 参数n (空格分隔)

9.3 函数内部使用参数的方式

函数内部是通过 位置变量 来使用参数的

$0 脚本名

$1~$9 调用函数时传递的第1到第9个参数 超过10个时 使用 {} 如 ${123}

如果函数中想使用命令行的参数,需要 调用函数时,通过参数传递给函数

如果想将命令行的所有参数都传递给函数 要注意下面的用法

函数名 $@

函数名 $*

函数名 "$@"

注意:上面三种传参方式 是将命令行的参数 原封不动的逐个传递给函数

而下面的用法是将命令行的参数作为一个整体 传递给函数

函数名 "$*"

#!/bin/bash 
function hqyj_test1(){
	for((i=0;i<5;i++))
	do
		echo "hello world $i"
	done
}
hqyj_test1 #没有参数的函数调用
echo "----------------------------------------"

#加法
function hqyj_add(){
	echo $(($1+$2))
}
hqyj_add 10 20 #有参数的函数调用1

结果:
hello world 0
hello world 1
hello world 2
hello world 3
hello world 4
----------------------------------------
30

# 把指定路径下的所有文件的 其他人的写权限 加上

#!/bin/bash 

function hqyj_chmod(){
	for i in `ls $1`
	do
		chmod o+w "$1/$i"
	done
	echo "--------------------"
	ls -l $1
	echo "--------------------"
}
hqyj_chmod /home/linux/stage2/day4 #函数调用
结果:
-rw-rw-rw- 1 linux linux 273 9月  14 20:59 33function.sh
-rw-rw-rw- 1 linux linux 207 9月  14 21:07 34funchmod.sh
-rw-rw--w- 1 linux linux  66 9月  14 20:05 a.c
lrwxrwxrwx 1 linux linux   3 9月  14 14:05 link -> a.c

如果函数中想使用命令行的参数 需要 调用函数时 通过参数传递给函数

#!/bin/bash 
function hqyj_test2()
{
	echo $1
	echo $2
	echo $3
	echo $4
}
hqyj_test2 hello world $1 $2

echo "--------------------------------"

function hqyj_test3()
{
	echo $1
	echo $2
	echo $3
}
#hqyj_test3 $@    #逐个传参
#hqyj_test3 $*    #逐个传参
#hqyj_test3 "$@"  #逐个传参
hqyj_test3 "$*"   #整体传参

结果:
hao
hello
world
hello
world
--------------------------------
hello world ni hao

9.4 函数的返回值

1.shell中的变量如果不加关键字 local 修饰 默认都是全局的

函数结束后 依然可以访问 所以可以使用全局变量来保存函数执行的结果

2.shell中也可以使用 return 来返回函数执行的结果

这种写法在调用处 需要使用 $? 来获取结果

这种写法只能返回 [0-255] 范围的值 超过这个值 就不能用了

3.可以使用echo来返回函数执行的结果

这种写法函数调用处需要使用命令置换符 $() 或者 `` 来接收

这种写法 函数中就只能有一句echo了 也就是说函数中就不能将信息打印到终端

如果有多句echo 那函数的返回值也是多个echo的结果 (空格分隔)

#!/bin/bash 
function hqyj_add1()
{
	RET1=$(($1+$2))
}
hqyj_add1 10 20
echo $RET1
echo "------------------------"

function hqyj_add2()
{
	return $(($1+$2))
}
hqyj_add2 20 30
echo $?
hqyj_add2 100 200
echo $?   #100+200大于255 
echo "------------------------"

function hqyj_add3(){
	echo $(($1+$2))
	#echo "hello" #如果写了 也会作为函数的返回值 不会按想象中的结果打印到终端
}
RET2=`hqyj_add3 10 20`
echo $RET2
RET3=$(hqyj_add3 1000 2000)
echo $RET3
结果:
30
------------------------
50
44
------------------------
30
3000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值