shell基础1

两条命令顺序执行命令间加;(cd /usr/ ; ls)
du 查看大小 du -sh du -sh*
wc -l 统计行数
选择指定的shell,声明shell位置 Sha-Bang
#!/bin/bash
#这里表示注释

bash  file.sh	 #(可以不用赋予执行权限就可以执行,会产生新的进程执行,执行完会回到当前目录)
 ./file.sh  	 #(必须要有可执行权限,会产生新的进程执行,执行完会回到当前目录)
source  file.sh  #(在当前进程运行,不会产生新的进程执行,执行完不会回到当前目录)
 .file.sh 		 #(在当前进程运行,不会产生新的进程执行,执行完不会回到当前目录)

默认输入设备:标准输入STDIN文件描述符:0 /dev/xxx
默认输出设备:标准输出STDOUT文件描述符:1 /dev/xxx
标准错误输出:STDERR文件描述符:2 /dev/xxx

输入重定向 < 命令 < file.txt
输出重定向 >(清空输入) >>(尾部追加) 2>(错误重定向) &>(输出全部重定向)

设置变量
read 变量名(手动输入变量)
echo $变量名 (读取变量)

在脚本内生产另一个文件
cat > /date/file.sh <<EOF (EOF指定结束符)
(这里输入要写入文件的内容)
EOF(表示要写入的内容在这里结束)

shell 变量不区分类型,弱类型
设置变量
read 变量名(手动输入变量)
echo $变量名 (读取变量)

变量名=值 a=123 (不允许空格)谨防手抖
let为变量赋值 let a=10/2 计算性能最低(解释性脚本语言)
命令赋给变量 l=ls
将命令结果赋给变量 name=$(ls-l /etc) 或者 name=`ls-l /etc`(反引号1旁边)
特殊字符或者空格可以用双引号""或单引号’'括起来,和python类似的字符串输出,单引号括双引号

变量的引用 :${变量名} $变量名 (变量的默认作用域为所在shell,不跨进程和shell)

变量的传递/导入 source filename.sh (将当前shell环境/进程的变量传递到脚本内,当前进程变量传递给子进程)
变量的导出 export (让当前shell环境/进程的变量可以让脚本读取到;子进程读取父进程变量,类似进程环境下的全局变量)

变量的删除
unset 变量名,能像python一样重新赋既重新定义

环境变量(linux全局变量)
env 查看现有的环境变量 echo $变量名
echo $PATH 命令搜索路径
环境变量追加 PATH=$PATH:/XXX/XX (在当前终端shell和子进程生效),写入文件永久生效 export 导出
终端提示修改 $PS1

set 查看预定义和位置变量

参数说明
$?查看上一条命令的执行状况 0 成功 $ perror 返回值 查看详细错误
$$查看当前程序的pid
$0查看当前的程序名/脚本名

输入脚本的位置参数 $1 $2 …${9} $1 传入的第一个参数
脚本内位置变量设置默认值 ${1}x (无论如何都保留x) ${1-x}(如果参数不为空则不生效,为空生效)

参数处理说明
$#传递到脚本的参数个数
$*以一个单字符串显示所有向脚本传递的参数。如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@ ∗ 相 同 , 但 是 使 用 时 加 引 号 , 并 在 引 号 中 返 回 每 个 参 数 。 如 " *相同,但是使用时加引号,并在引号中返回每个参数。如" 使"@“用「”」括起来的情况、以"$1" “ 2 " … " 2" … " 2""n” 的形式输出所有参数。
$-显示Shell使用的当前选项,与set命令功能相同。
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
#!/bin/bash
for pos in $*
do
  if [ "$pos" = "help" ]
      echo $pos
  fi
done

环境变量的配置文件 su - usrename 登录 login shell
所有用户公用
/etc/profile (系统启动,终端启动的环境配置文件,第一个被加载)
/etc/profile.d (不同的shell的对应脚本)
/etc/bashrc (系统命令别名配置,shell设置,第三个被加载)
用户家目录私有配置
~/.bash_profile (第四个被加载)
~/.bashrc(用户设置的命令别名,shell设置,第二个被加载)
重加载配置文件/函数库等
source /filepath/

定义数组、列表
list=(xx xx xxx xxxxx) 空格分割
显示所有元素 ${list[@]}
显示元素个数 ${#list[@]}
显示第一个元素 ${list[0]}

转义和引用
转移符号
引用 单引号‘’ 双引号“” 反引号 `` 单引号引用变量 完全引用会直接引用自身 不引用变量的值 双引号引用变量 不完全引用,会引用变量的值
注释 #
分号 分格符 ;

expr 算数运算 + - * / ** %
echo `expr 8 % 5`
sum=`expr 1 + 1`(数字和运算符间要空格,反引号)
数字常量
let a=8 let a=8+1 let b=08(8进制) let a=0xA(16进制)
((a=8)) ((a++)) echo $((1+1)) let的简写

特殊符号
引号
'单引号 完全引用 不解释内容直接引用
"双引号 不完全引用 解释内容
`反引号 执行命令

括号
() 单独使用会产生一个子shell (xyz=123) 定义数组
(())数字常量计算/赋值
$() 将括号内执行的命令的结果返回给变量 cmd=$(ls)

方括号
[] test 返回 0 1 [ 5 -gt 4 ]测试5大于4 真返回0
[[]] 比较数字的大小 [[ 5 > 4 ]] 真返回0

<> 大小于号 重定向符号

{} 输出范围 echo {0…9} 文件复制 cp /etc/xxx{.xyz} = cp /etc/xxx /etc/xyz

<>= 用在(()) [[]] let 里面

&& 与
|| 或
! 非

;; case语句分割符
: 空指令

测试
test [ ] 还可以拓展为[[ ]] 支持$$ || < > = !
判断字符串是否相等 [ “str1” = “str2”\ ] [ “str1” != “str2”\ ]

文件操作

参数说明
-e 文件名如果文件存在则为真
-r 文件名如果文件存在且可读则为真
-w 文件名如果文件存在且可写则为真
-x 文件名如果文件存在且可执行则为真
-s 文件名如果文件存在且至少有一个字符则为真
-d 文件名如果文件存在且为目录则为真
-f 文件名如果文件存在且为普通文件则为真
-c 文件名如果文件存在且为字符型特殊文件则为真
-b 文件名如果文件存在且为块特殊文件则为真

字符串

参数说明
=等于则为真
!=不相等则为真
-z 字符串字符串的长度为零则为真
-n 字符串字符串的长度不为零则为真

数字
[int1 -eq int2] (只支持整数)

参数说明
-eq等于
-ge大于等于
-gt大于
-le小于等于
-lt小于
-ne不等于

[[ 5 > 3 ]]
[ -e fail ](文件全路径) 判断文件是否存在 -d 判断是的为文件夹并存在 -f 是否存在并且是个普通文档

退出
exit
exit 10 返回10给shell,自定义执行返回值;返回值非0为不正常退出
$? 判断当前shell前一个进程是否正常退出

if
0 为true   非0为false   root 的uid为0

if-then

if [ 判断语句 ] 或者命令返回是否为0
then 
	执行相应语句
fi 结束
if [ $UID = 0 ]; then echo "123"; fi

if [ 判断语句 ] 或者命令返回是否为0 ;then
	为真执行的相应语句
else
	不为真执行的相应语句
fi

if [ 判断语句 ] 或者命令返回是否为0 ;then
	为真执行的相应语句
elif [ 判断语句 ] 或者命令返回是否为0 ;then
	为真执行的相应语句
else
	不为真执行的相应语句
fi

if [ 判断语句 ] 或者命令返回是否为0 ;then
	为真执行的相应语句
	if [ 判断语句 ] 或者命令返回是否为0 ;then
	       为真执行的相应语句
	fi
fi	


case "$变量" in
	"情况1"|"另一种情况1")    右括号表示结束一种情况
	命令...;;
	"情况2")
	命令...;;
	*)             #(\*通配符其他所有情况)
	命令...;;
esac
	
for 循环
for 参数 in 列表
	do  执行的命令
done   结束 封闭一个循环

使用反引号或者$()方式执行命令,命令的解惑当作列表处理

```bash
for filename in `ls *.txt`
	do
		mv $filename  $(basename $fliename .txt).mp3
done
#basename $fliename .txt   提取文件名

for ((变量初始化;循环判断条件;变量变化))
do
循环执行的命令
done

for ((i=1 ; i<=10 ; i++ ))
	do
		echo $i
done

while 循环

while test 测试成立
do
执行的命令
done

a=1
while [ $a -lt 10 ]
	do
		echo $a
		((a++))
done

while (( $a < 10 )); do echo $a ; ((a++)) ; done

while :   #恒为真,死循环

while [[ $c != "1" && $c != "2" ]]

until循环 为假执行 为真跳出循环

break 和continue 跳出循环
break 跳出整个循环
continue 跳出本次循环

i=0
for filename in /etc/profile.d/*.sh
	do
		if [ -x $filename ] ; then
			echo $filename
			i++
			if [ i -gt 5 ] ; then
				continue
			fi
			if [ i -eq 10 ] ; then
				break
			fi
		fi
		
done

while [ $# -ge 1 ]
do 
	echo $#
	if [ "$1" = "help" ]; then
		echo $1 this help
	fi
	shift
done


# shift 命令 位置参数可以用shift命令左移。比如shift 3表示原来的$4现在变成$1,
#  原来的$5现在变成$2等等,原来的$1、$2、$3丢弃。不带参数的shift命令相当于shift 1。