0 注意点:

1. 空格!
     因为shell 中空格是作为一个分隔符来判断命令 参数之间的关系的,所以很多地方要注意空格;

2. 变量:
    变量名: 下划线 字母  数字(不可以是开头)
    变量类型 : 统一按照字符串处理, 后面根据变量操作而变换类型

3. 函数定义:
        下面会有一些符号意义:
        $()和`` 是一组他在shell 中表示的是 命令的替换,就是在shell 中fork 一个子进程 区做 他们 括起来的命令 然后在返回父进程。 特别要注意的是在有system 调用的地方要放这种command的内嵌,是黑客攻击的对象。需要字符串化或者转义,但有一点要注意转义后就不要再字符符串化了。
        ${} 变量替换 就是把变量的真实值带入。
        $[]和$(()) 是一组 标识的是 算术运算 +-*/ ,下面有示例将某个变量值进行计算; 还有种方式: let cnt++
        [ ] 是test 的另一种格式 注意左右需要空格。
        [[ ]]  是加强的[] 可以有匹配 没有字符的分割。if等条件判断中会使用到;
        (()) 是一种可以支持数学运算符的 条件判断, 可当作 [] 用,只要其中的表达式符合c就可以。他和[[]]的区别是,(())可以支持 +-*/ 而[[ ]] 支持 匹配;

1. 基本格式 与 调试操作:

#!/bin/bash     
#这是用来注释

echo "hello shell! current path is "
pwd

ls -al

  a. 上面的示例中 #!/bin/bash 定义了解释器, 注释 通过 # 实现;

  b. 调试有两种方式;一种是在脚本编写中开启/关闭调试; 另一种是在调用过程中开启调试(bash -x);

脚本中增加调试步奏:

 脚本运行中通过bash -x 方式实现调试开启(其中+行就是脚本内容,下面是执行的结果)

 

2. 变量定义: shell变量是一种弱类型变量,不需要定义变量的类型;

  局部变量:local a = 12

  全局变量: 没有局部定义的关键字(local),就是全局变量

  其他注意点参考下面示例:

#!/bin/bash

a=12                 #定义中间不能有空格, a = 12 是错误的;
echo ${a}            #使用变量时候,必须要有$, 最好再用${a}
b="hello, world!"    #定义字符串时,有空格需要使用“”
echo ${b}
c=`pwd`              #可以使用命令的返回为值;
echo ${c}
d=$a:a
echo ${d}

 

常见的特殊变量:

$0 : 获取当前执行shell 脚本文件名,包含路径;
$n : 获取当前执行脚本的第n 个参数,n = 1... , 如果n > 9, 则需要将n 使用大括号括起来${12}
$* : 获取当前shell 的所有参数,将说有命令行参数视为单个字符串,相当于“$1$2$3"
$@ : 获取这个程序所有的参数,并保留参数之间的任何空白,相当于”$1" "$2" "$3", 这是将参数传给其他程序的好办法
$# : 得到执行当前脚本的参数个数
$? : 判断上一指令是否执行成功,0 成功, 非0 失败
$$ : 取当前进程的PID
$! : 上一个指令的PID

a=/dir/path/folder/link/filename.txt.log  

#非贪婪匹配(最小匹配)左删除
echo ${a#*/}  
echo ${a#*.}  
#非贪婪匹配(最小匹配)右删除
echo ${a%*/}
echo ${a%*.}

#贪婪匹配左删除
echo ${a##*/}
echo ${a##*.}
#贪婪匹配右删除
echo ${a%%/*}
echo ${a%%.*}

#shell字符串提取字串
echo ${a:5:6} #提取左边第5个字符往右的6个长度的字节内容

#字符串中变量值的替换
${a/f/F}    #替换第一个f
${a//f/F}   #替换所有的f

#${} 可以针对不同的状态(没设定,空值,非空值)进行赋值
${a:-my_file.txt} : 如果${a} 没有设定或为空值,则可以返回my_file.txt
类似的还有 (- :- = := + :+ ? :?) 等一系列的

3.输入输出

read [-option] -[variable...]

  -a array : 把输入赋值到数组array 中,索引从0 开始
  -d delimiter  : 用字符delimiter 中第一个字符指示输入结束,而不是一个换行符
  -e readline  使用readline 来处理输入,使得与命令行相同的方式编辑输入;
  -n num  读取num 个输入字符,而不是整行
  -p prompt : 为输入显示提示信息,使用字符串prompt
  -r raw mode : 不把 反斜杠 \  字符解释为转义字符
  -s silent mode   : 不显示输入
  -t seconds :  超时
  -u fd :  使用文件描述符 fd 中的输入,而不是标准输入;

echo : echo string
  -n : 删除默认换行
  -e : 开启转义

printf : printf format-string [arguments...]
  printf "%s is %d years old\n" Xiaoming 18

0: standard input(STDIN)
1: standard output(STDOUT)
2: standard error ouput(STDERR)

我们可以通过< 来改变读进的数据信道,还可以通过> 改变送出的数据到指定的文件中

ls newa* 1  1>file.out 2>file.err  #将STDOUT 保存到file.out 文件中,错误保存在file.err 文件中

 

 

 4. 函数

  有下面三种定义函数方式,注意区分函数中的${1} 与 全局中 ${1} 之间的差别

#!/bin/bash

#三种定义函数方式
function __func1__() {
   echo "$1"      #只能是当前函数的参数,可以将全局的${1} 传进来
   return 123
}

function __func2__ {
   echo ${1}
   return 234
}

__func3__() {
   echo ${1}
   return 345
}

__func1__ var1 var2
__func1__ ${1} ${2}  #这里的$1 与 __func1__ 中的$1 不一样,注意区分
echo $?

__func2__ var1 var2
__func2__ ${1} ${2}  #这里的$1 与 __func1__ 中的$1 不一样,注意区分
echo $?

__func3__ 
__func3__ 
echo $?

 

 

5. 流程控制 IF /case

if:

要用双中括号(功能比单中括号 更强大),前后必须有空格;以fi 结尾 

 man test 中显示各类比较方式,可以作为condition 表达式

#!/bin/bash 

if [[ condition ]]; then  #要用双中括号(功能比单个中括号 更强大),前后必须有空格;
   #statements
fi                                #以fi 结尾

if [[ condition ]]; then
   #statements
else
   #statements
fi

if [[ condition ]]; then
   #statements
elif [[ condition ]]; then
   #statements
elif [[ condition ]]; then
   #statements
else 
   #statements
fi

注意下面用法: \$[\${1} % 2] : $[] 用来计算整数表达式的值,只能整数计算

#!/bin/bash

for i in `ls -A`; do
   echo ${i}
done

read start end
for i in `seq ${start} ${end}`; do
   if [[ $[${i} % 2] -eq 0 ]];then
      echo ${i}
   fi
done

case :

#!/bin/bash 

case word in 
   pattern1 )
      ;;      #类似C 中break;
   pattern2 )
      ;;
   pattern3 )
      ;;
esac        #结束的标志
#!/bin/bash
read num
flag=$[ ${num} % 2 ]
case ${flag} in
   0 )
      echo "even"
      ;;
   1 )
      echo "odd"
      ;;
esac

 

6. 循环

for 循环:

for i in words; do
#for i in `seq ${start} ${end}`; do
#for i in `ls -A`; do
#for i in a b c d e; do
#for i in 1 2 3 4 5; do
   #statements
done

for (( i = 0; $i < 6; i++ )); do
   #statements
done
#!/bin/bash

cnt=0
function __count__() {
   for i in `ls -A ${1}`; do
      if [[ -f $1/$i ]]; then   #这里的文件要给绝对路径
         let cnt++
         echo ${i}
      fi

      if [[ -d $1/${i} ]];then  #这里的文件要给绝对路径
         __count__ $1/${i}
      fi

   done
   return 0
}

__count__ $1
echo ${cnt}

 

while 循环

#!/bin/bash
#format
while [[ condition  ]]; do
   #statements
done
#EXAMPLE
read num
i=1
while [[ $i != $num ]]; do
   echo $i
   i=$[$i + 1]   # $[] 用来计算整数表达式的值,只能整数计算, 例如$[${1} % 2];
done

until 循环:

#!/bin/bash
#format
until [[ condition ]]; do
   #statements
done
#EXAMPLE:
read num
i=1
until [[ $i -eq $num ]]; do
   echo $i
   let i++
done

 跳出 / 继续 控制 break/continue;

#!/bin/bash

read num
i=0
while [[ ${i} -lt ${num} ]]; do
   if [[ $[ ${num} % 2 ] != 0 ]]; then
      let num--
      continue
   fi

   if [[ ${num} -eq 4 ]]; then
      break
   fi
   
   echo ${num}
   #let num--
   num=$[ ${num} - 1 ]
done

 

 7. 数组

三种声明的方式:

declare -a a
name[subscript]=value
name=(v1, v2, v3 ...)

输出数组内容
${array[*]}
${array[@]}

数组元素个数
${#array[@]}

数组下标
${!array[@]}  #zsh 似乎不识别@
${!array[*]}

数组追加
array+=(a b c)

数组排序
sort

删除数组 与 元素
unset

注意点:1). zsh/bash中打印所有元素方式不同;

    2). bash 中下标从0 开始,zsh 下标从1 开始

 

posted on 2022-06-16 19:53  学海一扁舟  阅读(122)  评论(0编辑  收藏  举报