本文介绍: 不知道不全,希望有帮助

记录学习shell笔记整理一下方便以后忘记了回来学习


学习shell

第一个shell文件打印hello world!~

其实vi+文件名之前可以有另一个命令touch+文件名
因为vi+文件名表示打开文件(如果没有自动创建一个文件
touch+文件名表示创建一个新的文件

vi/vim hello	//创建一个叫hello文件
#! /bin/bash	//无实际意义,告诉我们这是用bash终端
echo "hello world~"/hello world!~	//两种方式可以可以不加单双引号echo就是输出的意思
sudo chmod +x hello
./hello
第二个shell文件,添加其他命令

例如:在hello文件中加入其他命令

vi/vim hello
echo "hello world"
echo -------------
cd /	//切换根目录
ls	//根目录下有那些文件
echo -----------------
date	//打印日期
./hello	//运行文件

基础知识

shell可以支持三种变量

1.自定义变量
1.1 变量名=值
haha=1
echo $haha

1.1.1变量命名规则

1.2 把一个变量赋值给另一个变量
a='hello'	//注意等号两边不能有空格
b=$a
echo $b
name=jack	//这里可以不加单引号
message=他的名字叫${name}!	//如果最后没有内容(这里是!),可以不用大括号{}
echo $message
1.3 定义只读变量
haha=1
echo $haha
readonly haha
1.4 删除变量:只能删除普通变量,不能删除只读变量
hehe=2
echo $hehe
unset hehe	//删除变量hehe
echo $hehe
2.环境变量:例如($PATH),可视全局变量
2.1 临时添加环境变量:只在当前终端有效,该终端关闭之后,变量就失效

export 变量名=变量值

export lala=1	//重启一个终端就无效
echo $lala

环境变量和普通变量的区别

export a=1
echo $a
b=2
echo $b
bash	//在该终端下开启子终端,终端里的终端
echo $b	//不会再显示了,普通变量不能在子终端中使用
echo $a
exit	//退出子终端
echo $b
unset a	//删除环境变量
echo $a
2.2 永久添加环境变量
2.2.1 方案一:添加完仅对当前用户有效切换其他用户其他用户不能使用这个环境变量
通过修改~/.bashrc文件,在最后一行添加上export 变量名=变量值,然后保存退出
 两种生效方法:
	1.关闭当前终端,重新打开一个新终端窗口就能生效
	2.输入"source~./bashrc"命令,立即生效
有效期限:永久生效
用户局限:仅对当前用户
vi .bashrc	//在主目录中打开
export haha=123456789	//找到最后一行,然后点击i开始插入所示代码,然后ESC,然后输入:wq保存退出
source ./bashrc	//让文件生效生效

多个终端打开可以输入然后看到123456789

echo $haha
2.2.2 方案
通过修改/etc/profile文件
sudo vi /etc/profile
export haha=1

生效方法系统重启
有效期限:永久有效
用户局限:对所有用户
sudo vi /etc/propile
export haha=1213131	//在文档最后一行输入,i表示插入,然后保存退出(同上)
echo $haha	//重启之后就可以使用在所有终端了
3.内部变量/位置参数/命令行参数linux提供的特殊类型变量,例如内部变量$$储存李当前进程进程
3.1  $0:编译脚本命令行
3.2  $n传递脚本函数参数n数字,$1表示第一个参数,以此类推
 当参数超过10个,用{}表示,例如${12}
3.3  $#:传递脚本函数参数个数
3.4  $*:传递脚本或函数的所有参数(所有参数可看作一个整体字符串)
3.5  $@:传递脚本或函数的所有参数(每个参数都是单独的字符)
3.6  $?:函数的返回值,或成为上个命令的退出状态(大部分命令执行成功时退出状态为0,失败为1)
3.7  $$:当前shell进程
vi haha
#! /bin/bash
echo 文件名:$0	//可加引号,可不加
echo 第一个参数:$1
echo 第二个参数:$2
echo 所有参数:$*
echo 所有参数:$@
echo 参数个数:$#
echo 当前进程ID:$$
bash haha 11 22 33	//haha是指文件名,后面三个是赋的值
vi haha
#! /bin/bash
set 11 22 33
echo 文件名:$0	//可加引号,可不加
echo 第一个参数:$1
echo 第二个参数:$2
echo 所有参数:$*
echo 所有参数:$@
echo 参数个数:$#
echo 当前进程ID:$$
4 变量值输出
4.1 命令echo
str="您好~" 
echo $str

与字符混用

str="您好!"
echo "$str,这是一个测试"

用{}与字符混用

month=9
echo "2021-${month}-10"

使用转义符,输出特殊字符

str="您好"
echo "$str",$"
4.2 命令printf

与echo类似

printf"您好!n"
可以带参数,和C语言python用法相同,%s表示字符串,%d表示整数
printf "我是一名%s,今年%d岁n" "学生" "30"

4.3 从用户输入获取变量值
使用read命令,类似与pythoninput
创建一个文件,展示read写法
vi test
#! /bin/bash
read -p "请输入两个数字" d1 d2
echo "输入的第一个数字是$d1"
echo "输入的第二个数字是$d2"
bash test
4.3 变量替换
4.3.1  ${haha}:正常使用变量haha
4.3.2  ${haha:-$hehe}:如果变量haha为空返回变量hehe的值,不改变haha的 值
4.3.3  ${haha:=$hehe}:如果变量haha为空,返回变量hehe的值,将hehe的值赋值给haha
4.3.4  ${haha:?$hehe}:如果变量haha为空,将hehe发送标准错误输出(终端)
		用来检测haha是否赋值,未被正常赋值脚本运行将暂停报错
4.3.5  ${haha:+$hehe}:如果变量haha被定义返回变量hehe的值,不改变haha的值
5. 数组
bash支持一维数组下标也是从0开始,数组元素空格分开
定义数组数组名=(值1 值2 ....值n)
shuzu=(A B C D)
echo ${shuzu[0]}	//取数组中的第一个值
echo ${shuzu[*]}	//取数组中的所有值
echo ${shuzu[@]}	//取数组中的所有值
echo ${#shuzu[@]}	//数组元素个数
echo ${#shuzu[1]}	//数组中第二个元素长度

6 数学运算
6.1 整数加减乘除
6.1.1 直接计算
echo $[1+1]
echo $[9-1]
echo $[9*3]
echo $[9/8]	//这个答案为1
6.1.2 计算并给变量赋值
a=$[1+1]
b=$[3-2]
c=$[7*1]
d=$[8/7]
echo $a $b $c $d
6.1.3 变量间的计算赋值
直接相加获得字符串
a=1
b=2
c=$a+$b
echo $c
使用let命令,获得数字结果
a=1
b=1
let.c=$a+$b
echo $c
使用双括号(())获得数字结果
a=1
b=2
((c=a+b))
echo $c
6.2 浮点数小数)加减乘除
6.2.1 加减
echo 1.1+2.2|bc
echo 2.1-2|bc	//小于1的小数之前的0被省略
printf %.2f `echo 2-1.3|bc	//保留两位小数,注意的是,这个不单引号,而是ESC下面那个键`
6.2.2 乘
其中scale控制保留小数点位数
echo "1.1*1.1"|bc
echo "scale=2;1.1*1.1"|bc	//小数点保留的位数为2
6.2.3 除
其中scale控制保留小数点位数
echo "4/3"|bc
echo "scale=3;4/3"|bc
6.3 计算并给变量赋值
c=$(echo "1.1*1.1"|bc)
echo $c

c=$(echo "scale=2;1.1*1.1"|bc)
echo $c
6.4 变量间计算赋值
a=1.1
b=1.2
x=$(echo "scale=3;$a*$b"|bc)
echo $x
7 流程控制语句
7.1 条件语句
7.1.1 if判断

if语句类型

 if...fi结构
	如果判断条件为真,就执行then后面的语句
	
	if [判断条件]		 //if和判断条件之间有一个空格,判断语句和[]之间也有空格
	then
		程序语句
	fi
vi test
a=3
b=3

echo a等于$a
echo b等于$

if [ $a == $b ]
then
    echo a等于b
fi

判断条件(逻辑表达式

判断条件介绍
用[ 判断条件 ]或者 test 判断条件,test常用
例:[ $a ==

b

]

b ]中

b]a和$b的两侧必须有空格

整数条件运算符

相等:-eq	例:[ $a -eq $b ] 或 [ $a == $b ]
不等于:-ne	例:[ $a -ne $b ] 或 [ $a != $b ]
大于:-gt	例:[ $a -gt $b ]
小于:-lt	例:[ $a -lt $b ]
小于等于:-ge	例:[ $a -ge $b ]
大于等于:-le	例:[ $a -le $b ]

字符串关系运算

相等:= 	例:[ $a = $b ]
不想等:!= 	例:[ $a != $b ]
检测字符串长度是否为0:-z	例:[ -z $a ]
检测字符串长度是否不为0:-n	例:[ -n $a ]
检测字符串长度是否为空:直接放入字符串变量	例:[ $a ]

文件测试运算

-d 检测文件是否是目录	例:f="/home/q.text"	[ -d $f ]
-f 检测文件是否是普通文件	例:[ -f $f ]
-r 检测文件是否可读	例:[ -r $f ]
-w 检测文件是否可写	例:[ -w $f ]
-x 检测文件是否可执行	例:[ -x $f ]
-s 检测文件大小是否大于0	例:[ -s $f ]
-e 检测文件是否存在	例:[ -e $f ]

布尔运算符

与:-a 	例:[ $a==$b -a $c==$d ]
或:-o 	例:[ $a == $b -o $c ==$d ]
非:! 	 	例:a=false 或 a=true [!$a ]

if...else...if结构
如果判断条件为真,就执行语句1
否则,执行语句2
if [ 判断条件 ]
then
	程序语句1
else
	程序语句2
fi
vi tst	
a=$1	//在这里其实有一个$0,但是$0输出得到的是该文件的名字,在这里无意义
b=$2

echo a等于$1
echo b等与$2

if [ $1 == $2 ]
then 
    echo a等于b
else
    echo a不等于b
fi
if...elif...if结构
如果判断条件1为真,就执行语句1,然后结束
如果判断条件1为假,进行判断条件2的判断,为真就执行语句2
否则,执行语句3
if [ 判断条件1 ]
then
	程序语句1
elif [ 判断条件2 ]
then
	程序语句2
else
	程序语句3
fi
a=$1
b=$2

echo a等于$1
echo b等于$2

if [ $a==$b ]
then
    echo a等于b
elif [ $a -gt $b] 
then
    echo a小于b
else
    echo a大于b
fi
if结构可以嵌套,一个If结构可以包含另一个if结构
if结构中的elif和else都是可选的,不必需有
7.1.2 case判断
case是一种多选择结构,可以匹配值,如果匹配成功,执行对应的语句,执行后结束,不执行其他语句

casein
值1)
	语句1
	;;
值2)
	语句2
	;;
值3)
	语句3
	;;
×)
	其他语句
esac
echo 1:榴莲
echo 2:椰子
echo 3:水蜜桃
echo 4:哈密瓜
echo 5:芒果
read -p “请选择你喜欢的水果:fruit	//这里需要在变量之前有一个空格,或者直接把变量之前的字符用双引号
case $fruit in
1)
	echo 你喜欢榴莲
	;;
2)
	echo 你喜欢椰子
	;;
3)
	echo 你喜欢水蜜桃
	;;
4)
	echo 你喜欢哈密瓜
	;;
5) 
	echo 你喜欢芒果
	;;
*)
	echo 你可能不喜欢水果
esac	

	
7.2 循环结构
7.2.1 while循环
while 判断条件
do
	语句
done

当判断条件为真时,循环执行语句,直到判断条件为假时,跳出循环
a=0
read -p 请输入一个数字:  num

while [ $a -lt $num ]
do
	echo $a
	((a=a+1))
done
cat tes	//可以看见文件中的代码
7.2.2 until循环
do
	语句
done

until 执行循环语句,直到until判断条件为真时结束
a=0
read -p 请输入一个数字: num

until [ $a == $num ]
do
	echo $a
	((a=a+1))
done

clear可以清除终端中的命令

5.2.3  for循环

for 变量 in 变量
do 
	语句
done

循环次数等于列表中元素个数,每次循环,变量值等于当前列表对应的元素
for x in 1 2 3 4 5 6 7 8 9
do
	echo $x
done
7.2.4 跳出循环
break
break 用来终止一个循环
break n ,其中n表示跳出循环的几层循环,默认是1
for x in 1 2 3 4 5 6
do 
	echo $x
	if [ $x == 2 ]
	then
		break
	fi
done
for x in 1 2 3
do
	for y in 3 4 5
	do
		if [ $x == $y ]
		then 
			echo x=$x,y=$y,x=y,跳出循环
			break 2
		else
			echo x=$x,y=$y,x!=y,循环继续
		fi
	done
done
continue
continue 用来跳过本次循环,直接进行下一次循环
continue n  ,其中n表示跳出的几层循环,默认是1
for x in 1 2 3 4 5
do
	if [ $x == 3 ]
	then 
		continue
	fi
	echo x=$x
done
exit
exit n, 退出当前终端,并设置退出值为n,不设置n默认为0
可使用$?查看最后一个命令的退出值
echo hello
exit 123
echo hello
echo  $?
7.3 多命令组合执行
7.3.1 &&

用法:命令1 && 命令2
含义:顺序执行命令1,命令2,但只有在命令1执行成功的情况下才执行命令2

cd / && l
// 首先进入目录,然后查询什么文件
rm qqq && l	//rm+文件名表示删除该文件
// 删除一个不存在的文件然后查询当前文件夹下有什么文件
7.3.2 ||

用法:命令1 || 命令2
含义:顺序执行命令1,命令2,但只有在命令1执行失败的情况下才执行命令2

cd / || l
//命令1进入目录,命令2查询当前目录有什么文件
cd haha || mkdir haha
//进入一个名叫haha的文件夹,当文件夹不存在(即命令1执行失败),创建一个名叫haha的文件夹
7.3.3 &&和|| 联合使用

用法:命令1 && 命令2 || 命令3
含义:从左往右看先看命令1和命令2,执行结果作为一个整体,可以这么理解(命令1 && 命令2)|| 命令3,括号里面两个命令都执行成功视为成功,则不执行命令3,有一个失败就视为失败,执行命令3

cd / && l || echo "命令1或命令2执行失败"

用法:命令1 || 命令2 && 命令3
含义:从左往右看先看命令1和命令2,执行结果作为一个整体,可以这么理解(命令1 || 命令2)&& 命令3,括号里面两个命令有一个执行成功视为成功,则不执行命令3,都失败就视为失败,执行命令3

cd / || l && echo "命令1或命令2执行成功"
7.3.4 使用括号()的组合命令

命令1 || (命令2 && 命令3)
命令1失败,执行(命令2 && 命令3),(命令2 && 命令3)看成整体

echo 1 || (echo 2 && echo 3)

8 函数
8.1 函数定义
函数名()
{
	函数内容
	return 返回值
}

函数的返回值只能是整数,如果不加return返回值,将会把最后一条命令的退出值作为返回值
8.2 函数调用

函数名 参数1 参数2 …

8.3 实例
8.3.1 调用函数打印hello world
touch hello
vi hello
hello()
{
	echo "hello world!~"
}
hello	//要想函数被调用,这里要写上文件名
bash hello或者./hello
8.3.2 在函数外部如何使用函数中的变量
shell 中的函数被调用后,函数外部直接使用内部定义的变量
hello()
{
	haha="hello world!"
}
hello
echo $haha
8.3.3 获取函数的输出值赋值给变量
hello()
{
	echo "hello world!"
}
haha=$(hello)
echo $haha
8.3.4 带返回值的函数
参数传递使用 $1  $2等表示,返回值用$?表示
love()
{
	((haha=$1+$2+$3))
	echo 第一个参数为 $1
	echo 第二个参数为 $2
	echo 第三个参数为 $3
	return $haha
}

love 3 6 4
echo love函数的返回值为$?
一些内置命令

read是shell内置命令,用于标准输入中读取数据并赋值给变量,如果没有进行重定向,默认就是从终端控制台读取用户输入的数据,如果进行了重定向,那么可以从文件中读取数据.

语法:read [options] [var1 var2]
options表示选项,如下所示,var表示用来存储数据的变量,可以是一个,也可以是多个
-n num 读取num个字符,而不是整行字符
-p prompt 显示提示信息,提示内容prompt
-s 静默模式,不会再屏幕显示输入的字符
-t seconds 设置超时时间,单位为秒,如果用户没有在指定时间内输入完成,那么read将会返回一个非0的退出状态,表示读取失败.

cat 文件名		//显示代码内容
#! /bin/bash			//说明脚本是用哪一种shell编写的,通常放在脚本第一行,从而调用相应的解释程序予以执行
#ShowHello
#To show hello to somebody

echo -n "Enter Your Name"	//参数-n的作用是不换行,echo默认换行
read name			//从键盘输入信息
echo "Hell0 $name"

Linux 系统中最常见的shell类型为Bourne shell(简称sh),C shell(简称csh),Korn shell(ksh),Bourne-again shell(简称bash)

1.命令记忆功能	./bash_history
2.自动补全功能	Tab键是个好东西
3.别名设置功能	alias ll='ls -l'	左边是新的名字右边是之前的名字或者属性
通配符
 *
*可以任意字符的0次或者多次出现
例如:

用户输入 ls -l file* ,在这个命令中,使用了通配符,shell在执行命令之前,会以合适的文件名进行替换找出当前目录中以file开头的文件名并执行。所以,当shell使用通配符时,在参数传递给程序之前,通配符已经变成实际文件名并执行。所以,当shell使用通配符时,在参数传递给程序之前,通配符已经变成实际文件名,如果通配符不能匹配任何文件,shell将会显示一个报错信息
* 可以匹配/(斜线)字符之外的任何字符,因为/用作路径名中的定界符


?
? 匹配任意个字符(除/之外)
d? 表示以‘d’开头的两个字符的文件名
??  表示任意个字符的文件名
?*y 表示至少两个字符,并且以“y”结束的文件名

[] 一对括号

[] 将一组字符列表括起来,其作用是匹配该字符组所限定的任何一个字符,即指定表中任意个字符。
例如:space.[co]匹配space.o或者space.c
[Hh]* 匹配以H或者h开头的文件名
[] 中无论有几个字符,都只代表个字符,在[]中,也可以用-指定字符的范围,例如[1-9]

{} 大括号
{string1,string2 ,sring3...}匹配string1或者其他的字符串
但这种写法只在bash,tcsh和C sh


输出时候有一个顺序执行,需要各个命令之间加上;
例如:
ls;date;pwd;cd /user
输入输出重定向
标准输入重定向:
command <fle	//将文件作为命令输入
//例如:bash < sho1的意思是让bash执行时,直接从sh01中读取数据,而不必交互式地从键盘上输入
//wc -l <file  表示统计file文件中有多少文本
command <<分界符	//从标准输入中读入,直到遇见分界符才停止

//
标准错误输出重定向:
command 2>file	//以覆盖的形式,把command中的错误信息输出到file文件中
command 2>>file	//以追加的形式,把command错误信息输出到file文件中
标准输出重定向:
command >file	//以覆盖的形式,把command中的正确结果输出到file文件中
command >>file	//以追加的形式,把command的正确信息输出到file文件中
管道
在shell中,管道实际上就是进程之间的一个通信工具,那么用在Linux命令中主要是方便两条命令互相之间可以相互通信。

管道符是"|",主要是把两个应用程序连接在一起,然后把第一个应用程序的输出,作为第二个应用程序的输入。如果还有第三应用程序的话,可以把第二个程序的输出,作为第三应用程序的输入,以此类推。

如 [ ls | grep test.s ],在当前文件过滤出test.sh文件:
[root@lincoding /]# ls 
bin   data  etc   lib    lost+found  net   opt   root  selinux  sys    usr
boot  dev   home  lib64  media       mnt   proc  sbin  srv   test.sh   tmp
[root@lincoding /]# ls | grep test.sh 
test.sh
管道符"|"就把ls命令的文件列表输出给到了[grep test.sh]命令来过滤文件。


管道符还有一个需要注意的地方,我们可以通过下面的命令观察到,在使用管道符的时候,管道符会为两条命令产生了子进程
[root@lincoding /]# cat | ps -f
UID         PID   PPID  C STIME TTY          TIME CMD
root       2627   2623  0 14:57 pts/0    00:00:00 -bash
root      88029   2627  0 19:51 pts/0    00:00:00 cat
root      88030   2627  0 19:51 pts/0    00:00:00 ps -f
进程bash的pid为2627,子进程catpid为88029,子进程ps -f的pid为88030。

由于管道符是会为连接的命令产生子进程,所以也是不会影响当前环境的。

我们用cd /home/ | ls命令验证下,运行结果如下
[root@lincoding /]# cd /home/ | ls 
bin   data  etc   lib    lost+found  net   opt   root  selinux  sys    usr
boot  dev   home  lib64  media       mnt   proc  sbin  srv   test.sh   tmp   
[root@lincoding /]# pwd
/
从以上的运行结果可以得知,类似切换目录cd这种会影响当前环境的命令,在使用了管道符之后,就没有对当前环境造成影响了。

如果使用分号";"连接两条命令会如何呢?
[root@lincoding /]# cd /sys/ ; ls
block  bus  class  dev  devices  firmware  fs  hypervisor  kernel  module  power
[root@lincoding sys]# pwd
/sys
可以得知,通过分号";"连接,cd命令会对当前环境造成影响

原文地址:https://blog.csdn.net/weixin_62529383/article/details/126844238

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_44930.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注