基础篇

基本语法

指定脚本解释器

#!
#!/bin/sh
#!/bin/bash

使脚本拥有执行权限

chmod +x     

.sh文件第一行必须指定解释器 或者使用 时直接指定

#!决定了脚本可以像一个独立的可执行文件一样执行 而不用在终端输入 sh bash python等等


注释

单行注释 #号

多行注释

:<<EOF
EOF

echo

echo会自动添加换行符
echo "输出字符串"  

#输出含变量的字符串
name=zp
echo "hello, \"${name}\""
# Output: hello, "zp"

#输出不换行字符串
echo -e ""       -e开启转义字符  开了-e才会识别换行
\c 表示不换行

#输出重定向文件  将输出到文件里面
echo "test" > test.txt 

#输出当前目录 `` 识别基本命令 获取结果
echo `pwd`

printf

# printf 不会输出换行符

变量

命名规则

#只能使用英文字母 数字 下划线 收割字符不能数字开头
#中间不能有空格
#不能使用标点
#不能使用bash里面的关键字

声明变量

# 语法形式为  ${var} 和 $var
world="hello"
echo ${word}
readonly word  #只读变量
unset word #删除变量

变量类型

#局部变量 仅在脚本内助有效的变量,其他程序和脚本无法访问
#环境变量  当前shell会话的所有程序和脚本 都有效 和局部变量创建很想 使用 export关键字

#常见的环境变量
    $HOME 当前用户目录
    $PATH 用分号分割的目录列表,shell回到这些目录查找命令
    $PWD  当前工作目录
    $RANDOM 0到32767之间的整数
    $UID    数值类型 当前用户的用户ID
    $PS1  主要系统输入提示符
    $PS2  次要系统输入提示符

字符串

单引号和双引号

#单引号的特点
    不识别变量
    里面不能出现单独的引号 转义字符也不行  可以成对出现 作为拼接字符串使用
#双引号
    识别变量 
    可以使用转义字符
    

基本使用

#获取变量长度
text="123456"
${#text}

#截取字符串
text="12345"
echo ${text:2:2}
输出34  相当于剪切了
#查找子字符串
text="hello"
echo `expr index "${text}" ll` 
查找 ll 在text里面的起始位置

数组

基本使用

#创建数组
nums =({2}=2 {0}=0)
color(red yellow "dark blue")
#访问数组
echo ${nums[1]}
#访问所有元素
echo ${color[*]}
echo ${color[{@]}
@会将元素扩展为一个单独的参数  中间的空格得以保留
#访问部分元元素
echo ${color{@}:2:0}
#长度
echo ${#nums[*]}

添加
colors=(white "${colors[@]}" green black)
echo ${colors[@]}
删除
unset colors[0]

运算符

算术运算符

#加减乘除 取余 使用 expr
expr  $x+$y
#=  赋值 ==比较
x=$y
[#x==$y]
x=10
y=20

echo "x=${x}, y=${y}"
#这里[[ 中间需要空格 ]]
if [[ ${x} != ${y} ]]
then
  echo "${x} != ${y}"
fi

关系运算符

-eq 是够相等   是返回true
-ne 是否不相等 否返回true
-gt    A大于B  则true
-lt    A小于B 则true
-ge    A大于B  则true
-le   A小于B 则true

布尔运算符

! 反过来 true变false 反之
-o  有一个true则true 相当于 or
-a    and运算符

逻辑运算符

&& 逻辑AND
|| 逻辑 OR

字符串运算符

= 字符串是否相当
!= 
-z 为0则true         
-n 不为0则true                         [ -n $a ]    
str 非空则true                        [ $a ]

文件测试运算符

-b file  块设备文件则true
-c file  字符设备文件 则true
-d file  目录则true
-f file 普通文件(不是目录,也不是设备文件)则true 
-g file   设置了 SGID则 true
-k file 设置了 沾着位这true
-p file 有名管道则true
-u 设置了SUID则true
-r file 文件可读则true
-w file
-x file 可执行
-s file 是否为空
-e file 文件或目录存在则 true

file = "/etc/hosts"
if [[ -r ${file} ]]:then
else
fi

控制语句

条件语句

bash中 [[]] sh中是[]  fi标志代码结束
if then elif  else fi

exec
case ${oper} in
  "+")
    val=`expr ${x} + ${y}`
    echo "${x} + ${y} = ${val}"
  ;;
  "-")
  echo ""
  ;;
 esac
 命令块之间要用;;分割

循环语句

for arg in elem1 elem2 elemN
do
done
#参数arg 依次被赋值为 elem1  elem2  可以用大括号扩展 不过需要加分号
for arg in {1..5};do
done
for ((i=0;i<5;i++));do
then

例子 
DIR=/home/zp
for FILE in ${DIR}/*.sh; do
  mv "$FILE" "${DIR}/scripts"
done
# 将 /home/zp 目录下所有 sh 文件拷贝到 /home/zp/scripts
#do和while一行的时候需要加分号
while 循环
while [[ 循环条件 ]];do
done

until [[ ]];do
done

#一般用来打印序列到屏幕,用户输入  使用break退出  continue跳过本次循环
select answer in elem1 elem2
do
done

函数

function 关键词可以不要 不写return的话 返回最后一条语令的结果  值类型只能返回0-255
返回值可以调用函数之后 $? 获得
使用之前必须定义, 然后调用  也就是  写了之后要调用一下 
function funname [()]{
}

位置参数

$0 脚本名称
$1 ... $9 第一到第九个参数列表
${10} ... ${N} 10到N个参数列别
$* or $ $@ 除了 $0之外所有位置参数
$#  不包括$0在内的位置参数的个数
$FUNCNAME   在函数内部有值

函数处理参数

$#    返回参数个数
$*    返回所有参数
$$    脚本运行的当前进程ID
$!    后台运行的最后一个进程的ID
$@    返回所有参数
$-   返回shell使用的当前选项 与set命令功能相同
$?  函数返回值

扩展

echo {00..8..2}  00 02 04 06
echo {0..5}  0 1 2 3 4 5
算术扩展  $(( ))
命令置换 ``或者 $()包围的时候会被之后   命令 被包围的时候会
now= `date`+%T
echo $now  输出时间 

流和重定向

输入输出

0  stdin    标准输入
1  stdout   标准输出
2  strerr   标准错误输出

重定向

>     重定向输出
&>    重定向输出和错误输出
&>>   以附加形式重定向输出和错误输出
<     重定向输入
<<     Here语法
<<<    Here字符串

grep da * 2>errors.txt  写到
less < errors.txt  读入

/dev/null
comman > /dev/null 2>&1

Debug

在脚本开始加选项
#!/bin/bash options
-f  禁止文件名展开
-i  让脚本以交互模式运行
-n  读取命令 不执行 用于检查
-t  执行第一条命令后退出
-v  执行每条语句钱向stderr输出该命令
-x  执行每条命令钱 向stderr输出该命令及命令的扩展参数
最后修改:2020 年 04 月 20 日 07 : 30 PM