Linux - shell 脚本学习

  shell 脚本是一种解释型语言。所以需要配套解释器来解释你的脚本。

一、解释器选择

  在脚本的第一行,就要注明你的脚本需要使用什么解释器来运行,比如#!/bin/bash,这个意思就是用/bin/bash来解析脚本。以下是常用的。

#!/bin/bash     <- 推荐
#!/bin/sh
#!/bin/ksh
#!/usr/bin/env bash    <- 推荐

  最后一种#!/usr/bin/env bash,通过/usr/bin/env运行程序,用户不需要去寻找程序在系统中的位置(因为在不同的系统,命令或程序存放的位置可能不同),只要程序在你的$PATH中。通过/usr/bin/env运行程序另一个好处是,它会根据你的环境寻找并运行默认的版本,提供灵活性。
  当然也可以自己定义一个脚本语言,用自己定义的解释器去解释他,比如你的解释器叫做xshell,放在/usr/local/bin下面。所以使用的时候就是#!/usr/local/bin/xshell

二、运行和调试

  一个脚本文件如何去运行呢,可以使用如下的方式运行脚本。

1、当前路径下运行
./test.sh
2、绝对路径运行
/tmp/test.sh
3、使用 . 运行
. test.sh
4、使用sh
sh test.sh
5、使用source
source test.sh 

  source、./ 、sh、. 这几种方式都可以运行脚本,但是这几种方式有一些区别。source和.和sh是在当前bash环境下读取并执行FileName中的命令。该filename文件可以无”执行权限”,sh更灵活带有很多参数,source常用来更新系统配置文件。./是打开一个子shell来读取并执行脚本中命令。
  脚本写完后需要调试,调试方式如下。

1、在脚本中, 不推荐
#! /bin/bash -x
2、在运行的时候
sh -x test.sh

  脚本调试中不推荐使用第一种方式,因为生产和测试的代码肯定是一样的,第一种方式还要去修改脚本代码,这种很容易忘了去修改回来,导致运行的时候都是调试信息。调试信息中前面带+或者++的表示执行的命令,不带的表示输出结果。

三、脚本基本语法

3.1、变量

  定义变量,key=value,主要分成两种动态变量和静态变量,静态变量就是数值是暂时不会变化的,习惯上字符串使用“”,数值的就不用引号;动态变量,值得是执行后才知道结果的值(常用于包含命令),使用反引号。

#静态变量
me="woshihaha"
#动态变量
date=`date`
echo ${me}
echo ${date}

3.2、传递参数

  传递的参数以$为开头。

字符 含义 讲解
$n 参数n,n从1开始 $1就是参数一,$2就是参数2
$0 当前脚本的文件名
$# 参数的个数
$* 所有的参数
$@ 所有的参数
$? 上个命令的退出状态,或函数的返回值。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

  $* 和 $@ 都表示所有参数,但是两者之间是有区别的。

脚本名称叫test.sh 入参三个: 1 2 3
运行test.sh 1 2 3$*"1 2 3"(一起被引号包住)
$@"1" "2" "3"(分别被包住)

3.3、数组

  数组都是一维的。 定义方式key=(value1 value2 value3 value4)

1、访问数组内元素,从0开始
echo ${arr[0]}
2、输出所有元素
echo ${arr[*]}
3、取数组的个数
echo ${#arr[*]}

3.4、判断

  用if判断,基本方法:

扫描二维码关注公众号,回复: 2397739 查看本文章
if [ "$a" == "$b" ]; then
elif[ "$a" == "CCC" ]; then
else
fi

当然如下这样子也是可以的

if [ "$a" == "$b" ]
then

else
fi

  需要注意的是[]的内部两边是要有空格。等于号两边也要有空格
  if判断有一堆的参数,如下

参数 含义 样式
-z 是否为空串 [ -z $myvar ]
-f filename 如果 filename为常规文件,则为真 [ -f “${A}”/start-dfs.sh ]
-gt 大于 if [ $# -gt 1 ]=>参数大于1
-e 当pathname指定的文件或目录存在时返回真 [ -e $myvar ]
-ge 大于等于 [ $# -ge 1 ]
-n 非空串
-eq 等于 [ $# -eq 1 ]

3.5、循环

  循环主要用到两种,for循环和while循环。

for x in 1 2 3 4 5
do
    echo $x
done 

  for循环除了用in,还可以这样for ((i=1;i<10;i++)),这种方式很像Java代码。while循环:

i=1
while(($i<10))
do
    echo $i
    let "i++"   
done

3.6 case

  像其他语言switch一样,有条件的选择。

case "$promer" in
    "A")
      echo "A"
    ;;
    "B"|"C")
      echo "A"
    ;;
    *)
      echo "A"
    ;;
  esac

四、常用方法

4.1 获取当前脚本所在路径

  获取当前脚本的所在的路径有两个问题需要注意下。
  第一,pwd确实是用于获取绝对路径,但是如果你的shell脚本是test.sh,运行的时候不是本地运行,而是在上层目录运行的(如:shell/test.sh),这个时候的pwd就是上层父目录的地址。
  第二,$0,这个在不同的调用时候有不同的含义。

建议的写法:
BASEPATH=$(cd `dirname $0`; pwd)
解析:
dirname $0   <- 去除文件名中的非目录部分,仅显示与目录有关的内容,即文件所在当前目录
cd           <- 进入这个目录          
pwd          <- 获取该目录的路径

4.2 变量配置

  可以进行变量的条件替换,既只有某种条件发生时才进行替换。

变量配置方式 str 没有配置 str 为空字符串 str 已配置非为空字符串
var=${str-expr} var=expr var= var=$str
var=${str:-expr} var=expr var=expr var=$str
var=${str+expr} var= var=expr var=expr
var=${str:+expr} var= var= var=expr
var=${str=expr} str=expr
var=expr
str 不变
var=
str 不变
var=$str
var=${str:=expr} str=expr
var=expr
str=expr
var=expr
str 不变
var=$str
var=${str?expr} expr 输出至 stderr var= var=$str
var=${str:?expr} expr 输出至 stderr expr 输出至 stderr var=$str

4.3、分割字符串

  字符串要按照某种特殊字符进行分割,如下:

s="1,2,3,4,5"
OLD_IFS="$IFS"
IFS=","
arr=($s)
IFS="$OLD_IFS"
for x in ${arr[*]}
do
    echo $x
done

  讲解:IFS这个是hash内部的域分隔符,需要保留之前的值,在字符串再转数组的时候,自动使用IFS将字符串切分。
  或者,如下使用的替换“,”为“ ”方式,然后转化成数组。

arr2=(${s//,/ })
for x in ${arr2[*]}
do
    ehco $x
done

猜你喜欢

转载自blog.csdn.net/myt0929/article/details/80874915