.sh文件是什么
是UNIX/LINUX操作系统的脚本文件,用记事本就可以打开是Bash(一种Unix shell)编程的脚本它以纯文本格式存储用Bash语言编写的指令可以通过在Shell的命令行界面中输入文本命令来执行。
.sh文件怎么运行
可以将sh改为EXE,这样就是一个应用程序双击运行Linux系统:
cd到.sh文件所在的目录./xxx.sh (要有执行权限)命令后输入句对路径执行(要有执行权限)在.sh文件路径下执行 sh xxx.sh直接执行sh 绝对路径 sh 命令执行不要求x权限
对于文件x权限
可以目录文件夹下输入命令 ll
没有权限可执行 chmod u+x 文件名.sh
给所有用户添加执行权限: chmod a+x 文件名.sh
注意查看是否有文件执行权限,有权限会显示绿色。
什么是bash
Bash是一种命令语言,通常运行于文本窗口中能执行用户直接输入的命令,还能从SH文件中读取命令一般作为内置于操作系统的应用程序向用户提供访问操作系统内核的服务
bash语法
shell所有语句不需要使用分号 ; 进行终结执行shell脚本文件等价于在bash窗口即时逐行执行语句,所以某一行的语法错误或执行错误不会影响后续语句的执行无需声明变量,或者说直接给某个变量名赋值则相当于声明了该变量赋值语句的等号 = 两边不能有 空格 ariable="abc"使用变量,需要在变量名前面加上 $,在变量名两边加上大括号 {}, 大括号一般情况下可缺省,主要为了帮助解释器识别变量的边界,在部分必要情况下不可缺省
echo $variable #可缺省
echo ${variable}
echo "I am good at ${skill}Script"
#如果使用的是skill变量则大括号不可缺省,缺省时解释器会使用skillScript变量
只读变量 使用 readonly 命令可以将变量定义为只读变量,被定义为只读变量后变量无法再被赋值
url="www.google.com"
readonly url
url="www.baidu.com" #赋值失败
删除变量,使用 unset 命令可以删除变量,使该变量重新回到赋值之前的状态(即未定义状态),输出为定义变量时shell解释器的行为是输出一个空行,同时只读变量无法被删除变量类型 在运行shell时,会同时存在如下三种变量 局部变量:在脚本或命令中定义,仅在当前shell实例中生效 环境变量:定义在os中,所有的程序(包括shell)都可以访问环境变量,有的程序需要环境变量作为参数来运行,shell脚本中也可以定义环境变量 shell变量:由shell程序(解释器)设置的特殊变量,一部分是环境变量,一部分是局部变量
数据类型
shell脚本与其他脚本语言的优势在于环境兼容性强,劣势在于不适合复杂度较高,要进行数据结构比较复杂的操作时最好使用其它复杂脚本语言(如python),然后使用shell进行调用即可
字符串 使用 单引号、双引号 或 不使用引号, 单引号中的任何字符都会原样输出 而双引号支持转义字符和变量, 另外连续的字符串会直接拼接而无需操作符
name="bob"
echo "hello,$name!" #hello,bob!
echo "hello,"$name"!" #hello,bob!
echo 'hello,$name!' #hello,$name!
echo 'hello,'$name'!' #hello,bob!
数字 直接将数字给变量赋值即可,但是shell默认只支持整数运算而不支持浮点数运算,需要算术运算时使用 expr 本质上解释器 大部分时候 将数字当作字符串处理的,expr只是将字符串转化为数字进行算术运算并将结果重新以字符串返回
a=10
b=-5
echo `expr $a + $b` #5
数组使用小括号来表示数组,数组元素之间用 空格 分开,两边用 小括号() 包围 支持一维数组(不支持多维数组) 下标由0开始,可以使用不连续的下标,下标的范围也没有限制
array=(value0 value1 value2)
echo ${array}
#不指定下标时直接读取第0个元素的值
echo ${array[0]}
#读取数组的第0个元素的值(这种情况大括号无法省略,否则或读取$array变量)
echo ${array[@]}
#使用@符号获取数组中所有元素
array[0]=5
#修改第0个元素的值
# 使用#获取数组或字符串变量的长度,但是不能获取常量的长度
str="string"
array=(1 "abcdefg" -8)
echo ${#str} #6
echo ${#"string"} #报错 “string”是字面值&常量
echo ${#array[@]} #3 返回数组长度3
echo ${#array[1]} #7
echo ${#array[2]} #2(-8仍然被当作"-8"字符串处理)
运算符
使用expr, 命令多元运算符的两边必须有 空格 value=expr 2 + 2
算术运算符: +、-、*、/、% 乘号*前边必须加反斜杠()转义才能实现乘法运算
关系运算符 关系运算符仅适用于数字,其中=和!=不仅适用于数字也适用于字符串的比较 -eq(=) equal 判断是否相等 -ne(!=) not equal 判断是否不等 -gt(>) greater than 判断是否大于 -ge(>=) greater equal 判断是否大于等于 -lt(<) less than 判断是否小于 -le(<=) less equal 判断是否小于等于
逻辑运算符 , 仅适用于运算符两边均是布尔值的运算 ! 非运算 -o(||) 或运算 or -a(&&) 与运算 and
字符串运算符 = 判断是否相等 !=判断是否不等 -z zero 判断字符串长度是否为0 -n not zero 判断字符串长度是否不为0 $ 判断字符串是否不为空,即该变量是否存在,存在时返回true
文件检测运算符 文件检测运算符适用于检测Unix文件的各种属性,作为路径字符串的单元操作符 -b block 判断路径是否是块设备文件 -c char 判断路径是否是字符设备文件 -d directory 判断路径是否是目录路径(即文件夹) -e exist 判断路径是否存在(即该路径对应一个文件或者目录) -f file 判断路径是否是文件路径(既不是目录也不是设备文件) -r read 判断文件是否可读 -w write 判断文件是否可写 -x exec 判断文件是否可执行 -s 判断文件是否不为空(文件大小是否大于0)
流程控制语句
条件判断
if condition1
# condition语句一般使用 中括号[] ,包含返回布尔值的运算符的运算语句
# 如 [ a == b ],且变量名与中括号之间必须有 空格
then
command1
command2
commandN
elif condition2;then #用;可以代替换行
command3
else
command4
#elif分支或else分支没有任何指令执行,则不能写这个分支,否则解释器会报错
fi
循环 for循环 可遍历变量列表、数组或二者的组合
for var in item1 item2 ${array[@]} item3 itemN
do
command1
command2
done
while/until循环 condition是终止条件且循环体至少执行一次
while/until condition
do
command1
command2
done
break和continue 和其它语言一样,break命令跳出循环体执行后面的语句,continue跳出本次循环而不影响后面循环的执行
选择语句 case xxx in形式的选择语句,类似于其它语言的switch case语句 ;; 表示break *)表示default,使用esac结束该选择语句
case $value in
"value1")
echo "case1"
;;
"value2")
echo "case2"
;;
*)
echo "case default"
;;
esac
函数 函数没有对应的局部变量栈 传入函数的参数在函数内部通过$n来获取
a=1
# 函数声明: 其中`function`和`()`二者可以缺省一个,`()`和`{}`之间的空格也可以缺省
function funcName() {
echo $1
echo $a
b=2
return 3
}
# 函数调用 函数名后面是空格分开的参数列
funcName "param1" param2 # param1 1
# 在函数调用完成后通过$?获取 return语句返回的数值(0-255)
echo $? #3
echo $b #2
注释
# 多行注释
:< a = 1 EOF 常用命令&约定 shell强大之处在于可以调用所有环境变量Path中的程序 #!是shell文件开始部分一个约定的标记(和python声明文件编码类似),它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell, 如:#!/bin/bash即声明该shell脚本使用bash解释执行 参数处理 在执行shell脚本时,通常需要向脚本传递参数,在脚本内通过 $n 获取参数,n代表参数的位置从1开始, 因为无法以纯数字作为变量名所以并不会冲突,但是超过10后必须使用 ${n} 获取避免歧义。 下面还有一些特殊字符处理参数 $# 参数总个数$* 以单字符串返回脚本传递的所有参数(一般用于log)$@ 返回每个参数构成的数组(一般用于遍历)$- 显示shell当前使用的选项,和set命令对应$? 返回上一条命令(包括函数调用)的退出状态 0表示正常返回 文件引入 . 或 source 进行引入,是类似include的概念,当解释器识别到文件包含指令时,会将对应文件中的文本替换到包含指令中再进行执行。 . fileName1 #包含fileName1文件 source fileName2 #包含fileName2文件 文件引入和直接执行其它shell的区别 文件引入形式执行的shell文件不需要有可执行权限,只需要有可读权限,因为shell将包含文件的文本内容视为shell本身的一部分。文件包含的shell脚本和原shell共享所有变量,是在同一个进程中执行的;而第二种方式直接执行的shell是作为当前父进程下的子进程执行的,只能通过传入参数的方式将变量传入子进程,且子进程中各项变量和操作在结束后不会传回父进程(只能设置一个返回值)。所以某种意义上来说执行其它shell更像是一次函数调用。