linux 从头开始その八(shell script)

终于撑到了 shell script

写在前面:

  • 命令是自上而下,自左而右的
  • 空格和空白行将被忽略
  • 当读取到一个ENTER,就尝试执行该行命令
  • 一行命令太多可以用 \enter 换行
  • # 为注释
  • 直接命令执行, shell.sh 文件必须有xr权限
  • 绝对路径执行
  • 相对路径执行
  • 变量PATH, 写入脚本来执行
  • 通过命令sh shell.sh <==> bash shell,sh 或 source shell.sh  (这个命令跟前面的有差别, 后面说)

 

日上フブキ的第一个脚本:

mkdir bin;cd bin
vim hello.sh

  #!/bin/bash
  # 这是随便写的注释
  PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
  export PATH
  echo -e "Hello world! \a \n"
  exit 0

关于上面脚本要BB的一些事情:

  • 第一行的 #!/bin/bash   不是注释, 告诉系统,我这个bin下的文件是要是用的bash语法的,bin是可变的, 要根据所在位置变化
  • # 就是注释
  • PATH 说的是环境变量, 一般都这么配置。作用就是调用外部命令, 如在脚本里加 ll -a / 就能正常执行,否则没这个PATH, 会报错,说找不到ll 命令。这是因为配置好PATH, 就可以直接用外部命令了, 而不用写下它绝对路径引用。总之一句话,就是要写这个PATH
  • 返回值, exit退出 返回0, 说明程序正常执行
  • 执行时, 直接在当前目录 sh.hello.sh
  •  

下一个脚本, 能与用户交互

#!/bin/bash
  PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
  export PATH 
  read -p "input your fname" fname
  read -p "input your lname" lname
  echo -e "\n Your name is ${fname} ${lname}"

 

下面根据日期创建文件名

${filesuer:-"filename"}  相当给一个默认名, filesuer为空即用户输入为空时,用filename

date1=$(date --date='2 days ago' +%Y%m%d)     最坑的是这个,'2 days ago‘ 用单引号, +%Y%m%d 这个+一定要和前面的有个空格

#!/bin/bash
  PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
  export PATH 
  read -p "input your filename" fileuser
  filename=${filesuer:-"filename"}
  date1=$(date --date='2 days ago' +%Y%m%d)
  date2=$(date --date='1 days ago' +%Y%m%d)
  date3=$(date +%Y%m%d)
  file1=${filename}${date1}
  file2=${filename}${date2}
  file3=${filename}${date3}
  touch "${file1}"
  touch "${file2}"
  touch "${file3}"

 

下面利用$(())   进行简单的数值计算, 默认只支持整数

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

echo -e "input 2 num \n" 
read -p "first num" fnum
read -p "second num" snum
total=$((${fnum}*${snum}))
echo -e "\n ${total}"

下面稍微改动下,能支持小数计算了, 加了个bc

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

echo -e "input 2 num \n" 
read -p "first num" fnum
read -p "second num" snum
echo -e "\n ((${fnum}*${snum}))" | bc



下面说说,启动脚本命令sh 和 source 的区别

1 sh命令是bash 的别名, 使用它, 相当于开启了一个新的子进程,开启一个新的bash环境,重点在于,子进程完成后,在子进程内的各项变量或操作将会结束而不会回传到父进程中。就是说,用sh开启个脚本, 运行完, 回到父进程,在调用脚本变量,是不能调过来的。

2 source 来执行脚本, 是在父进程中来执行脚本的, 可以用脚本里的变量。

 

有些nb的test命令

-e文件名是否存在
-f改文件名是不是文件
-d改文件名是不是目录
-r文件名是不是有可读权限
-w文件名是不是又有写入权限
-x文件名是不是有可执行权限
-u有没有suid权限
-g有没有sgid权限
-k有没有sticky bit 权限
-s是不是空文件夹
下面test file1 -nt file2
-nt后面接两个文件, 判断文件1是不是比文件2新
-ot1是不是比2旧
-ef1和2 是不是同样一个文件夹 
下面test n1 -eq n2  n1 和n2 是两个整数
-eq两个数是不是相等
-ne两个数不相等
-gtn1 大于 n2
-ltn1 小于 n2
-gen1 大于等于 n2
-len1 小于等于 n2
test -z string判断字符串是否为0?若为空, 返回True
test -n string字符串为空, 返回False
test str1 == str2两个字符串是不是相等
test str1 != str2是不是不相等
下面多重条件判断
-atest -r filename -a -x filename    -a 是and
-o是or
!不等于

 

test -e /xx    判断xx存不存在    直接执行不会显示任何结果

test -e /xx && echo "exit" || echo "not exit"

小例子

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

echo -e "input a filename, I will check the filename's type and permission. \n\n"
read -p "input a filename" filename
test -z ${filename} && echo "you must input filename" && exit 0
test ! -e ${filename} && echo "the filename '${filename}' is not exit " && exit 0
test -f ${filename} && filetype="reg"
test -d ${filename} && filetype="dir"
test -r ${filename} && perm="r"
test -w ${filename} && perm="${perm} w"
test -x ${filename} && perm="${perm} x"
echo "the filename: ${filename} is a ${filetype}" 
echo "and per is ${perm}"

 

上面的test也可用[]

[ -z "${HOME}" ] ; echo  $?

千万注意!!!!

[空格 -z "{HOME}"空格]           [空格"$HOME"空格==空格"$MALL"空格]       [] 两边得有空格, 里面的组件也要有空格

  • 中括号内的每个组件都需要有空格
  • 中括号的变量最好用双引号括起来
  • 中括号内的常数最好用单引号或双引号括起来
  • 小demo
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

read -p "please input (Y/N)" yn
[ "${yn}" == "Y" -o "${yn}" == "y" ] && echo "ok" && exit 0
[ "${yn}" == "N" -o "${yn}" == "n" ] && echo "fuck it" && exit 0
echo "i don't know what your choice" && exit 0

 

shell script 的默认变量

sh hello.sh opt1 opt2 opt3 opt4

     $0          $1    $2     $3    &4

脚本的名字是 第零个变量  $0 ,    $1 第一个变量  。。。。

$#代表参数的个数,不含$0,  本例是4
$@["$1" "$2" "$3" "$4"]     记这个
$*["$1c$2c$3c$4"]     c是分割符, 默认是空格
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

echo "the script name is${0}"  
echo "total paramether number is $#"
[ "$#" -lt 2 ] && echo "the number of parameter is less then 2. stop" && exit 0
echo "your whole parameter is $@"
echo "${1}"
echo "${2}"

输入 xx.ch 1 2 3 4

还有个 shift 偏移变量

&{1} --> 1

shift 2   去掉前两个变量

&{1} --> 3

 

条件判断式

1 if then

if [条件判断]; then
         条件成立时,执行
fi 结束if判断



if [条件判断]; then
         条件成立时,执行

else
         条件成立时,执行

fi 结束if判断


if [条件判断]; then
         条件成立时,执行

elif [条件判断];then
         条件成立时,执行

else
         条件成立时,执行

fi 结束if判断
[ "${yn}" == "Y" -or "${yn}" == "y" ] 
等价于
[ "${yn}" == "Y" ] || [ "${yn}" == "y" ]
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

read -p "input" yn
if [ "${yn}" == "y" ] or [ "${yn}" == "Y" ]; then
        echo "ok"
        exit 0
fi

2 利用case esac

case $变量 in
   "第一个变量的内容")
       程序段
       ;;
   "第二个变量的内容")
       程序段
       ;;
*)
     不包含第一个和第二个变量的内容执行此处
     exit 1
      ;;
esac
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 
case ${1} in 
   "hello")
	echo "hello "
	;;
   "")
	echo "please input"
	;;
	*)
	echo "fuck it"
	;;
esac

 

利用function 功能

shell script 中的function  必须写在程序的前面。

#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

function printit() {
           echo -n "your choice is ${1}"   # ${1} 是这个行数的第一个参数
}


case ${1} in 
   "one")
	    printit 1
	    ;;
   "two")
	    printit 2
	    ;;
    "three")
	    printit 3
	    ;;
    *)         
        echo "user ${0} {one|two|three}"
        ;;
esac

 

不定循环

while do done

当condition 成立时一直执行

while [ condition ]
do 
    xxxxxx
done

untile do done

当condition 成立时退出循环

until [ condition ]
do 
   xxxx
done
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

s=0
i=0
while [ "${i}" != "100" ]
do 
       i=$(($i+1))
       s=$(($s+$i))
done
echo "the result is  $s"

 

固定循环

for do done

for var in con1 con2 con3
do 
     xxxx
done
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

for i in aki desky enako
do 
   echo "${i}"
done
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

users=$(cut -d ':' -f1 /etc/passwd)
for i in ${users}
do 
	id ${i}
done
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

network="192.168.1"
for i in $(seq 1 100)
do  
   xxx
done

想说的就是 $(seq 1 100), 1到100

for do done  的数值处理

for ((初始值; 限制值; 赋值运算;))
do 
   xxx
done
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH 

read -p "input a num " nu
s=0
for (( i=1; i<=${nu}; i=i+1 ))
do 
	s=$((${s}+${i}))
done
echo "result ${s}"

 

shell 脚本的跟踪和调试

sh

-n   不要执行脚本, 仅查语法问题

-v   在执行脚本前, 先将脚本的文件内容写在屏幕上

-x   将使用的脚本内容显示到屏幕上

 sh -n hello.sh      语法没问题, 无任何显示


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值