shell个人学习笔记(基础)

参考:https://www.runoob.com/linux/linux-shell.html

1.特别强调:

脚本的执行方式两大种:
1.在.sh文件当前目录下使用: 
	/bin/sh test.sh 或 /bin/bash test.sh
	说明:/bin/sh 和 /bin/bash 使用的解析器不同,有的语法不支持,
2.在.sh文件当前目录下使用: 
	chmod +x ./test.sh  # 将文件变为可执行文件 
	./test.sh # 执行当前可执行文件
3.文件是在windows系统创建后传送到linux系统时,文件类型不正确(dos类型),
	需要在vim编辑状态下修改文件类型(unix):  set ff=unix
4.shell中变量作用域:默认为global(全局),在函数中需要尽量使用local(局部)指定为局部变量,
避免方法调用时,使用到同名的变量,导致数据出错。

5.以下语法在bash解析器中使用,在sh解析器中可能会报错

2.变量:

2.1定义 str="hello world"  注意:等号前后不能空格
2.2引用 echo ${str}  或 echo $str  # 打印在控制台
2.3命名规范: 同java
2.4设置只读: readonly str   # 设置后不能再次赋值
2.5删除变量: unset str   # 删除后不能在引用

3.字符串:

3.1单引号:变量和转义符号不生效,原样展示
	echo '\"${str}\" 你好'     # 结果: \"${str}\" 你好
3.2双引号:可以解析变量和转义符号
	echo "\"${str}\" 你好"     # 结果: "hello world" 你好
3.3字符串拼接:直接将两个变量紧挨一起,中间不用任何符号
	echo "hello""world"   # 结果: helloworld
3.4截取子串: ${str:1:3}  # 结果: ell  从索引1,取3个,起始索引为0
3.5长度:  ${#str}  # 结果: 11
3.6查找子串:  echo `expr index "${str}" eo`  # 结果: 2    
	说明:查询出e或o中第一个出现的位置

4.数组:

4.1定义:使用括号加空格
	方式1 array=("11" "2" "35")
	方式2 array=(
			"11"
			"2"
			"35"
		  )	
	方式3 array[0]="11"
4.2引用: 
	${array[0]}  # 结果: 11 
	${array[@]} 或 ${array[*]} # 数据所有元素
4.3数组长度:  ${#array[@]}  或  ${#array[*]}
	注意:${#array[0]} # 表示数组第一个元素的长度,结果: 2  

5.参数传递:

#!/bin/bash
echo "shell 参数传递实例"
echo "执行的文件名: $0";
echo "第一个参数为: $1";
echo "第二个参数为: $2";
echo "第三个参数为: $3";
echo "=============================="
echo '参数个数$# '$#;
echo '所有参数$* '$*;
echo '脚本运行的当前进程ID号: '$$;
echo '后台运行的最后一个进程ID号: '$!;
echo '所有参数$@ '$@;
echo '所有参数"$@" '"$@";
echo '退出状态$? '$?

为脚本设置可执行权限,并执行脚本,同时传递参数,参数以空格分割
chmod +x test.sh 
./test.sh 1 2 3

echo '=============$* 与 $@ 区别=================='
echo '$*返回一个值,$@返回的多个值'
echo '-- $* 演示 ---'
for i in "$*"; do
		echo $i
done    

echo '-- $@ 演示 ---'
for i in "$@"; do
		echo $i
done

结果:
=============$* 与 $@ 区别==================
$*返回一个值,$@返回的多个值
-- $* 演示 ---
1 33 54
-- $@ 演示 ---
1
33
54

6.运算符

6.1 基本运算符
原生bash中不支持简单数学运算,通过其他命令实现,如awk和expr
加:	`expr ${a} + ${b}`
减:	`expr ${a} - ${b}`
乘:	`expr ${a} \* ${b}`
除:	`expr ${a} / ${b}`
取余:	`expr ${a} % ${b}`
赋值:	a=${b}
数字相等:	[${a} == ${b}]  返回true或false
数字不等:	[${a} != ${b}]	返回true或false
注意:在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 "*" 不需要转义符号 "\" 。

例子
#!/bin/bash
# 算术运算
a=10;
b=20;
echo "a + b = `expr ${a} + ${b}`";
echo "a - b = `expr ${a} - ${b}`";
echo "a * b = `expr ${a} \* ${b}`";
echo "a / b = `expr ${a} / ${b}`";
echo "a % b = `expr ${a} % ${b}`";
if [ ${a} == ${b} ]
then
		echo "a 等于 b"
fi
if [ ${a} != ${b} ]
then
		echo "a 不等于 b"
fi
6.2 关系运算符
-eq 相等  [ $a -eq $b ]
-ne 不相等 [ $a -ne $b ]
-gt 大于
-lt 小于
-ge 大于或等于
-le 小于或等于

例子,同上使用if语句
6.3 布尔运算符
!  非     [ ! false ] 
-o  或  [ $a -lt 20 -o $b -gt 100 ] 
-a  与  [ $a -lt 20 -a $b -gt 100 ]
6.4 逻辑运算符
&&  逻辑and   [[ $a -lt 100 && $b -gt 100 ]] 
||	逻辑or    [[ $a -lt 100 || $b -gt 100 ]]
注意: 必须加两个中括号  [[]]
6.5 字符串运算符
=  检验相等,相等返回true    	[ $a = $b ]
!= 校验不等,不等放回true		[ $a != $b ]
-z 校验长度为0,为0返回true		[ -z $a ] 
-n 校验长度不为0,不为0返回true	[ -n "$a" ] 
$  校验非空,非空返回true		[ $a ]
6.6 文件测试运算符: 用于检测 Unix 文件的各种属性
常用:
-r file	可读,是=>true	[ -r $file ] 返回 true。
-w file	可写,是=>true	[ -w $file ] 返回 true。
-x file	可执行,是=>true	[ -x $file ] 返回 true。
-s file	为空(文件大小是否大于0),不为空返回 true。	[ -s $file ] 返回 true。
-e file	文件或目录是否存在,是=>true 	[ -e $file ] 返回 true。
-d file	是目录,是=>true	[ -d $file ] 返回 false。
-f file	是普通文件(既不是目录,也不是设备文件),是=>true	[ -f $file ] 返回 true。

不常用:
-b file	是块设备文件,是=>true	[ -b $file ] 返回 false。
-c file	是字符设备文件,是=>true	[ -c $file ] 返回 false。
-g file	设置了 SGID 位,是=>true	[ -g $file ] 返回 false。
-k file	设置了粘着位(Sticky Bit),是=>true	[ -k $file ] 返回 false。
-p file	有名管道,是=>true	[ -p $file ] 返回 false。
-u file	设置了 SUID 位,是=>true	[ -u $file ] 返回 false。

7.echo命令

7.1 普通字符串
echo "it is a test"
结果: it is a test
echo it is a test 
结果: it is a test
7.2 显示转义字符
echo "\"it is a test\""
结果: "it is a test"
7.3 显示变量
#!/bin/sh
read name
echo "${name} it is a test"
结果: 张三   # 输入的内容
	  张三 it is a test  #输出
7.4 显示换行
echo -e "it is a test \n"  # -e开启转义
echo "zhangsan"
结果: it is a test

	  zhangsan
7.5 显示不换行
echo -e "it is a test \c"  #-e开启转义  \c 不换行
echo "zhangsan"
结果: it is a test zhangsan
7.6 显示结果定向到文件
echo "it is a test" > myfile
7.7 显示原样字符串 ,用单引号
echo '$name \"'
结果: $name \"
7.8 显示命令执行结果
echo `date`
结果: Thu Jul 24 10:08:46 CST 2014

8. printf命令

语法: printf  format-string  [arguments...]

实例1: 
	printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg  
	printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
结果:
	姓名     性别   体重kg
	郭靖     男      66.12
说明:
	%s 字符串,%d 整型,%c 一个字符,%f 小数
	10:10个字符宽
	-: 左对齐,没有则右对齐
	\n: 换行,默认不换行
	
实例2:
	# format-string为双引号
	printf "%d %s\n" 1 "abc"
	结果: 1 abc
	
	# 单引号与双引号效果一样
	printf '%d %s\n' 1 "abc"
	结果: 1 abc
	
	# 没有引号也可以输出
	printf %s abcdef
	结果: abcdef
	
	# 格式只指定了一个参数,但多出的参数仍然会按照该格式输出,format-string 被重用
	printf %s abc def
	结果: abcdef
	printf "%s\n" abc def
	结果: 
		abc 
		def	
	printf "%s %s %s\n" a b c d e f g h i j
	结果: 
		a b c
		d e f
		g h i
		j  
		
	# 如果没有 arguments,那么 %s 用NULL代替,%d 用 0 代替
	printf "%s and %d \n"
	结果:   and 0

printf 的转义序列
	\a	警告字符,通常为ASCII的BEL字符
	\b	后退
	\c	抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),
	    而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
	\f	换页(formfeed)
	\n	换行
	\r	回车(Carriage return)
	\t	水平制表符
	\v	垂直制表符
	\\	一个字面上的反斜杠字符
	\ddd	表示1到3位数八进制值的字符。仅在格式字符串中有效
	\0ddd	表示1到3位的八进制值字符

实例3:
	# %s不解析字符串中的转义符号
	$ printf "a string, no processing:<%s>\n" "A\nB"
	a string, no processing:<A\nB>
	# %b解析字符串中的转义符号
	$ printf "a string, no processing:<%b>\n" "A\nB"
	a string, no processing:<A
	B>

9. test命令 (就是if判断后的[]的另一种写法)

9.1 数值测试
	-eq	等于则为真
	-ne	不等于则为真
	-gt	大于则为真
	-ge	大于等于则为真
	-lt	小于则为真
	-le	小于等于则为真
实例:
	num1=100
	num2=100
	if test $[num1] -eq $[num2]
	then
		echo '两个数相等!'
	else
		echo '两个数不相等!'
	fi
注意: 代码中的 [] 执行基本的算数运算,如:result=$[num1+num2]
9.2 字符串测试
	=			:等于则为真
	!=			:不相等则为真
	-z 字符串	:字符串的长度为零则为真
	-n 字符串	:字符串的长度不为零则为真
实例:
	str1="abcd"
	str2="bcd"
	if test -n ${str1}
	then
	echo "str1长度不为0"
	else
	echo "str2长度为0"
	fi
	
	if test -z ${str2}
	then
	echo "str2 size is zero"
	else
	echo "str2 size is not zero"
	fi

	if test ${str1} = ${str2}
	then
	echo "str1 equals str2"
	else
	echo "str1 not equal to str2"
	fi
9.3 文件测试
	-e 文件名	:如果文件存在则为真
	-r 文件名	:如果文件存在且可读则为真
	-w 文件名	:如果文件存在且可写则为真
	-x 文件名	:如果文件存在且可执行则为真
	-s 文件名	:如果文件存在且至少有一个字符则为真
	-d 文件名	:如果文件存在且为目录则为真
	-f 文件名	:如果文件存在且为普通文件则为真
	-c 文件名	:如果文件存在且为字符型特殊文件则为真
	-b 文件名	:如果文件存在且为块特殊文件则为真
实例:
	echo "检查/root目录下是否有shell目录,结果如下:"
	cd /root
	if test -d ./shell
	then
	echo "shell文件存在,且为目录"
	elif test -e ./shell
	then
	echo "shell文件存在,不为目录"
	else
	echo "shell文件不存在"
	fi

注意: 还提供 -a -o ! 操作。  优先级:!最高 -a次之 -o最低
实例2
	cd /bin
	if test -e ./notFile -o -e ./bash
	then
		echo '至少有一个文件存在!'
	else
		echo '两个文件都不存在'
	fi

10. 流程控制

10.1 条件语句
10.1.1 简单if
	if condition
	then
		command1
		command2
		...
		commandN
	fi
写成一行(适用于终端命令提示符):	
	if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
	
10.1.2 if else
	if condition
	then
		command1
	else
		command2
	fi
	
10.1.3 if else-if else
	if condition
	then
		command1
	elif condition2
		command2
	else
		command3
	fi
注意: condition处可以用test命令,也可用[] ( 如:[ $a -eq $b ] )
10.2 循环
10.2.1 for循环
	for var in item1 item2 ... itemN
	do
		command1
		command2
		...
		commandN
	done
	
	写成一行: for var in item1 item2 ... itemN; do command1; command2… done;
实例:
	array=(1 2 3)
	# 循环数组打印所有值
	for var in ${array[@]};
	do
		echo ${var};
	done;

10.2.2 while循环
	条件为true时继续,false时停止循环
	
	while condition
	do
		command
	done;

实例:
	#!/bin/bash
	int=1
	while(( $int<=5 ))
	do
		echo $int
		let "int++"
	done

说明: let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中
	  不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。
	自加操作:let no++
	自减操作:let no--
	简写形式 let no+=10,let no-=20,分别等同于 let no=no+10,let no=no-20。
	
实例:
	# while 用于读取键盘信息
	echo '按下 ctrl + D 退出'
	printf "输入你的名字:"
	while read input
	do
	 echo "${input}! 是个帅哥"
	done;

10.2.3 无限循环
	while :
	do
		command
	done
	或
	while true
	do
		command
	done
	或
	for (( ; ; ))
	
10.2.4 until循环
	until条件为true时停止,与while相反(true继续)
	
	until condition
	do
		command
	done
	
实例:
	echo "输出0-9,如下:"
	y=0
	until [ ${y} -gt 9 ]
	do
	 echo "${y}"
	 y=`expr ${y} + 1`
	 # let "y++"; # Bash 的let命令
	done
	
10.2.5 case ... esac
	等同于java中的switch ... case
	每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,
	跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。
	*) 放最后等同于default
	
	case 值 in
	模式1)
		command1
		command2
		...
		commandN
		;; # 等同break
	模式2)
		command1
		command2
		...
		commandN
		;;
	esac
	
实例:
	echo '输入1 - 4 之间的数子'
	printf "你输入的数字为:"
	read aNum
	case ${aNum} in
		1) echo '你选择了1';;
		2) echo '你选择了2';;
		3) echo '你选择了3';;
		4) echo '你选择了4';;
		*) echo '你选择了1-4之外的数字';;
	esac
	
10.2.6 break命令(跳出循环)
10.2.7 continue命令(跳过当前循环)
实例:
	# 要求:输入1-5之间的数字,继续游戏,否则结束
	while :
	do
	  printf "请输入1-5之间的数字:"
	  read inNum
	  case ${inNum} in
	  1|2|3|4|5) printf "你输入的数字是:%s !\n" ${inNum}
	  ;;
	  *) echo "你输入的数字不在1-5之间,游戏结束 ! "
		 break
	  ;;
	  esac
	done

11. 函数

11.1 函数格式:
[ function ] funname [()]  
{
	action;
	[return int;]
}
说明: []中的内容为非必选
	1.可以写作 function fun()定义,也可写作 fun()定义,不带任何参数
	2.return 加返回值,不加则以最后一行命令的结果进行返回
11.2 函数参数
	函数内,通过 $n 的形式来获取参数的值,n>= 10时,需要用${10}方式获取
	$#	传递到脚本或函数的参数个数
	$*	以一个单字符串显示所有向脚本传递的参数
	$@	与$*相同,但是使用时加引号,并在引号中返回每个参数。
	$$	脚本运行的当前进程ID号
	$!	后台运行的最后一个进程的ID号
	$-	显示Shell使用的当前选项,与set命令功能相同。
	$?	显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

实例:
	# 带有返回值的函数
	fun3() {
	  # 对两个数进行相加
	  #return $(($1+$2))
	  return `expr $1 + $2`
	}

	echo -e "请输入数字1:\c"
	read a
	echo -e "请输入数字2:\c"
	read b
	fun3 ${a} ${b}
	echo "两数的和为:$?"

注意:
	1.$?不能哥着其他命令获取,只能跟着函数后,
	不然获取的是第二个$?上一条命令的函数成功与否的数字含义
	2.函数的定义必须放在调用之前,不然解析不到

实例:
	# 求数组的所有值的和
	sum(){
	  # x=(1 2 3 4 5 6 7 8 9 10)
	  x=$1
	  sum=0
	  for var in ${x[@]}
	  do
		sum=`expr ${sum} + ${var}`
	  done
	  echo ${sum}
	  return ${sum}
	}

	arr=(1 2 3 4 5 6 7 8 9 10)
	sum "${arr[*]}"
	echo "数组的和为:$?"
注意:
	数组参数的传递,必须写成字符串形式  "${arr[*]}"
	
	经过测试: 
	如果函数参数传递数组: 如 sum ${arr} 等同于 sum 1 2 3 4 5 6 7 8 9 10 ,一共传递了10个参数
	在函数中使用 echo $2 ;echo $3 分别获取到了2和3的值,得已验证了以上结论
	故使用字符串形式将数组的所有值放在字符串中,如 "${arr[*]}"
	
	如下不写在函数中,则不用字符串
	arr=(1 2 3 4)
	for v in ${arr[*]}
	do
	echo ${v}
	done

12. 输入/输出重定向

命令               	说明
command > file		将输出重定向到 file。
command < file		将输入重定向到 file。
command >> file		将输出以追加的方式重定向到 file。
n > file			将文件描述符为 n 的文件重定向到 file。
n >> file			将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m				将输出文件 m 和 n 合并。
n <& m				将输入文件 m 和 n 合并。
<< tag				将开始标记 tag 和结束标记 tag 之间的内容作为输入。
12.1输出重定向
	command1 > file1  将command1的输出结果存入file1
实例:
	who > file1  执行who命令,将用户信息存入file1,如果file1中有内容,则将覆盖
	who >> file1  将内容追加到file1尾部
12.2输入重定向
	command1 < file1  将file1的内容写入标准输入(STDIN)中,再提供command1使用
实例:
	wc -l file1   :-l(为英文L的小写) 打印文本的行数  结果为 2 file1
	wc -l < file1   :结果为 2  ,没有文件名,因为命令仅知道标准输入读取的内容
	wc -l < file1 >> file1  :不打印结果,将 wc -l < file1 的结果 "2" 追加到file1文件中
12.3Here Document
	特殊重定向,将输入的文本段,重定向到标准输入中
	command << delimiter
		document
	delimiter
实例:
	在命令行中用 wc -l命令计算 Here Document的行数
	$ wc -l << EOF
		欢迎来到
		菜鸟教程
		www.runoob.com
	EOF
	结果:
	3          # 输出结果为 3 行
	
	
实例:	
	#!/bin/bash

	cat << EOF
	欢迎来到
	菜鸟教程
	www.runoob.com
	EOF
	
	结果:
	欢迎来到
	菜鸟教程
	www.runoob.com
12.4 /dev/null 文件
	如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
	command > /dev/null
	/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么
	也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。
	
	$ command > /dev/null 2>&1
	注意:0 是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
	这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。

13. 文件包含

13.1 文件引入方式
. filename # 注意点号和文件名中间有一个空格
或
source filename
13.2 被引用的文件不需要有可执行权限
实例:
	1)创建test1.sh文件,文件内容如下:
	#!/bin/bash
	name="张三"
	
	2)创建test2.sh文件,文件内容如下:
	#!/bin/bash
	# 引入test1.sh文件
	. ./test1.sh
	# source ./test1.sh
	# 使用test1.sh文件中的变量
	echo "${name}是男的"
	
结果:
	张三是男的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值