什么是shell
两重含义:
1、壳,此时shell是一个用 C 语言编写的应用程,是用户与内核实现交互的窗口
2、一门解释性的脚本编程语言
3、具体的shell源码,常以.sh结尾
shell程序第1行
最常见的是以下面这个字符串开头:
#!/usr/bin/sh
在 shell 脚本, #! 告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 解释器。 #! 被称作shebang(也称为 Hashbang )。 所以,你应该会在 shell 中,见到诸如以下的注释:
指定 sh 解释器
#!/bin/sh
指定 bash 解释器
#!/bin/bash
常见的shell如下:
名称 | 描述 |
---|---|
sh | 即 Bourne Shell。sh 是 Unix 标准默认的 shell |
bash | 即 Bourne Again Shell。bash 是 Linux 标准默认的 shell。即bash是sh的扩展,有更强大的语法功能 |
fish | 智能和用户友好的命令行 shell。 |
xiki | 使 shell 控制台更友好,更强大。 |
zsh | 功能强大的 shell 与脚本语言。 |
shell的语法坑
当你从其它语言转过来的时候,一定会不太适应shell的几个语法坑
对空格的使用
-
在if else语法中,if与后面的表达式必须有空格隔开,这对于熟悉其他语言的程序员来说很容易将其忽略,导致面对语法错误的提示百思不得其解。
-
if [ expression ] then Statement(s) to be executed if expression is true fi
如果then与if在同一行,则需要分号分割.
if [ expression ];then
Statement(s) to be executed if expression is true
fi
多元素表达
在表达多个元素时,元素之间是采用空格个来分隔,比如:
# 定义数组
array_name=(value0 value1 value2 value3)
#函数参数
printf "%d %s\n" 1 "abc"。
为什么不能使用逗号呢?估计是历史原因吧。
变量定义
定义变量时,变量名和等号之间不能有空格!!!
myNum =10 # 错误,等号前有空格
myNum=10 # 正确
注释
# 单行注释
:<<EOF
多行注释
EOF
###################
#注释测试
###################
通常我们可以将单行注释#作为多行注释使用。可以达到多行注释的效果
echo
# 输出普通字符
echo "hello,world"
# 输出变量
val="hello,world"
echo "${val}"
#输出换行符 ,注意-e 是开启转义,不能少。少了就自动换行
echo -e "YES\nNO"
# 输出重定向
echo "test" > test.txt
# 输出执行结果(例如当前路径在“/home/roboslyq”,则下面语句会输出/home/roboslyq)
echo `pwd`
变量
弱变量类型语言
跟许多程序设计语言一样,你可以在 bash 中创建变量。 Bash 中没有数据类型,bash 中的变量可以保存一个数字、一个字符、一个字符串等等。同 时无需提前声明变量,给变量赋值会直接创建变量。
声明变量 访问变量的语法形式为: ${var} 和 $var 。 变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,所 以推荐加花括号。
#!/usr/bin/env bash
################### 声明变量 ###################
name="world"
echo "hello ${name}"
# Output: hello world
################### 只读变量 ###################
rword="hello"
echo ${rword}
# Output: hello
readonly rword
# rword="bye" # 如果放开注释,执行时会报错
################### 删除变量 ###################
dword="hello" # 声明变量
echo ${dword} # 输出变量值
# Output: hello
unset dword # 删除变量
echo ${dword}
# Output: (空)
字符串
在shell中,可以使用单引号,双引号或者不使用引号
其中单引号里的字符串不会支持变量连接,而双引号支持变量链接。例如:
hello='hello,world'
'a ${hello}' # 结果是a ${hello}
'${hello}' # 结果是 hello,world
"a,${hello}" # 结果是a,hello,world
双引号可以包含双引号,只需要转义即可。但单引号不行。
获取字符串长度
hello="hello,world"
echo ${#hello} # 输出11
截取字符串
hello="hello,world"
echo ${hello:2:2} # 输出ll,从第 3(编号从0开始,所以2对应第3个字符) 个字符开始,截取 2 个字符长度
查找字符串所有位置
hello="hello,world"
echo ${hello:2:2}
echo `expr index ${hello} 'll' `
示例汇总
#!/usr/bin/env bash
################### 单引号和双引号 ###################
################### 拼接字符串 ###################
# 使用单引号拼接
name1='white'
str1='hello, '${name1}''
str2='hello, ${name1}'
echo ${str1}_${str2}
# Output:
# hello, white_hello, ${name1}
# 使用双引号拼接
name2="black"
str3="hello, "${name2}""
str4="hello, ${name2}"
echo ${str3}_${str4}
# Output:
# hello, black_hello, black
################### 获取字符串长度 ###################
text="12345"
echo "${text} length is: ${#text}"
# Output:
# 12345 length is: 5
################### 获取字符串长度 ###################
text="12345"
echo ${text:2:2}
# Output:
# 34
################### 查找子字符串 ###################
text="hello"
echo `expr index "${text}" ll`
# Output:
# 3
################### 截取关键字左边内容(保留右边) ###################
full_branch="feature/1.0.0"
branch=`echo ${full_branch#feature/}`
echo "branch is ${branch}"
################### 截取关键字右边内容(保留左边) ###################
full_version="0.0.1-SNAPSHOT
version=`echo ${full_version%-SNAPSHOT}`
echo "version is ${version}"
################### 判断字符串中是否包含子字符串 ###################
result=$(echo "${str}" | grep "feature/")
if [[ "$result" != "" ]]; then
echo "feature/ 是 ${str} 的子字符串"
else
echo "feature/ 不是 ${str} 的子字符串"
fi
数组
定义
# 创建数组:小括号 然后是中括号表时下标并初始化变量值
array=([0]=1 [1]=2)
# 数组取值
echo ${array[0]}
# 获取数据所有元素
echo ${array[*]}
echo ${array[@]}
# 元素循环遍列(for语句)
for element in ${array[@]};do
echo $element
done
#记数器i遍列
for i in $(seq 0 ${array[@]});do
echo ${array[i]}
done
MAP使用
declare -A SEGMENT_SEQ=(["NA"]="01" ["AL"]="02")
echo ${SEGMENT_SEQ["NA"]}
# 会输出01
# 或者不需要declare也行
SEGMENT_SEQ=(["NA"]="01" ["AL"]="02")
echo ${SEGMENT_SEQ["NA"]}
# 会输出01
普通操作符
表达式计算,注意:条件表达式要放在方括号之间,并且要有空格,例如: [$x==$y] 是错误的,必须写 成 [ $x == $y ]
#!/usr/bin/env bash
x=10
if [[ -n $1 ]]; then
x=$1
fi
y=20
if [[ -n $2 ]]; then
y=$2
fi
echo "x=${x}, y=${y}"
val=`expr ${x} + ${y}`
echo "${x} + ${y} = $val"
val=`expr ${x} - ${y}`
echo "${x} - ${y} = $val"
val=`expr ${x} \* ${y}`
echo "${x} * ${y} = $val"
val=`expr ${y} / ${x}`
echo "${y} / ${x} = $val"
val=`expr ${y} % ${x}`
echo "${y} % ${x} = $val"
if [[ ${x} == ${y} ]]; then
echo "${x} = ${y}"
fi
if [[ ${x} != ${y} ]]; then
echo "${x} != ${y}"
fi
# Execute: ./operator-demo.sh
# Output:
# x=10, y=20
# 10 + 20 = 30
# 10 - 20 = -10
# 10 * 20 = 200
# 20 / 10 = 2
# 20 % 10 = 0
# 10 != 20
# Execute: ./operator-demo.sh 10 30
# Output:
# x=10, y=30
# 10 + 30 = 40
# 10 - 30 = -20
# 10 * 30 = 300
# 30 / 10 = 3
# 30 % 10 = 0
# 10 不等于 30
let和expr
# 要想达到预期结果,用下列三种方法:
# let不需要$符号
let "var+=1"
#$(()),注意不是{}
var=$((var+1))
var=$[$var+1]
var=`expr $var + 1`#注意加号两边的空格,否则还是按照字符串的方式赋值。
For循环
与C语言很像:
for arg in elem1 elem2 ... elemN
do
### 语句
done
写成一行,用分号分割:
for arg in elem1 elem2 ... elemNdo
### 语句
done
同时也支持正常的像java高级语言一样的for循环
for (( i = 0; i < 10; i++ )); do
echo $i
done
exp:
#!/usr/bin/env bash
################### for 语句 ###################
echo "print 0 to 9"
for (( j = 0; j < 10; j ++ )); do
echo ${j}
done
# Output:
# print 0 to 9
# 0
# 1
# 2
# 3
# 4
# 5
# 6
# 7
# 8
# 9
################### for in 语句 ###################
echo "print 1 to 5"
for i in {1..5}; do
echo ${i};
done
# Output:
# print 1 to 5
# 1
# 2
# 3
# 4
# 5
################### for in 语句遍历文件 ###################
DIR=/home/zp
for FILE in ${DIR}/*.sh; do
mv "$FILE" "${DIR}/scripts"
done
# 将 /home/zp 目录下所有 sh 文件拷贝到 /home/zp/scripts
while循环
while [[ condition ]]
do
### 语句
done
start=0
end=50
while [ "$start" -le "$end" ]; do
printf '%s\n' "$start"
start=$((start+1))
done
Until循环
i=0
until [ ${i} -gt 5 ]; do
echo ${i}
#i=`expr ${i} + 1`
let "i++"
done
#输出如下:
0
1
2
3
4
5
文件操作
if [ -d '/home/test' ];then
echo "y"
else
echo "n"
fi