Linux命令行与shell脚本编程大全 part 2

shell脚本编程基础

 

chapter 11 构建基本脚本

chapter 12 使用结构化命令

chapter 13 更多的结构化命令

chapter 14 处理用户输入

chapter 15 呈现数据

chapter 16 控制脚本


chapter 11 构建基本脚本

(等号为变量赋值时,变量,等号,值之间不能有空格)

引用变量时,要用美元符号,不然系统会将变量名当作字符串

将命令输出赋值给变量,(1 反引号字符(`)与~号在同一个键盘位置,2 $)

输出重定向 (命令 > 文件) (覆盖文件数据)(命令 >> 文件)(在文件尾追加数据)

输入重定向 (命令 < 文件) ,内联输入重定向(命令 << 数据)

管道连接(命令1 | 命令2 | ... | 命令n),(Linux系统同时运行这两个命令,在系统内部将它们连接起来,第一个命令产生输出的同时,输出会被立即送到第二个命令,数据传输不会用到任何中间文件或者缓冲区)

数学运算(加减乘除等)在方括号内,如var4=$[$var1 * ($var2 - $var3)],(只支持整数运算)

要用内建bash计算机来进行浮点运算(命令 bc进入,输入quit退出)(浮点运算要设置内建变量scale,其代表运算结果小数点保留位数)

查看退出状态码,echo $?。exit + 一个数,可以自己指定退出状态码,但是这个数字最大只能是255

chapter 12 使用结构化命令

如果if后面的命令的退出状态码是0,执行then部分

if 后不能接命令之外的条件判断,其他条件用test,或者[]

if command
then
   commands
elif test condition
then
   commands
elif [condition]
then
   commands
else
   commands
fi

数值大小比较,n1 -eq(相等),-ne(不等),-gt(大于),-lt(小于),-ge(大于等于),-le(小于等于) n2

在test数值大小比较中,不能使用浮点值。

字符串比较

str1 =,!=,<,> str2(大于小于号必须转义,否则会被当作重定向符号)

-n(检查字符串长度是否非0),-z(检查字符串长度是否为0) str1

#!/bin/bash
val1=baseball
val2=hockey
if [ $val1 \> $val2 ]
then
   echo "$val1 is greater than $val2"
else
   echo "$val1 is less than $val2"
fi

文件比较,检查文件是否可读可写,是否是目录等

符合条件测试,允许&&和||

if else 里允许双括号,也就是((a++, !, ~, **, <<, >>, &, |, &&, ||)),这些逻辑运算和位运算等

也允许双方括号,也就是[[模式匹配(正则表达式)]]

chapter 13 更多的结构化命令

for 循环

list="Alab Alas Ariz Arka Colo"
list=$list" Conn" #向字符串尾部添加文本


IFS.OLD=$IFS
IFS=$'\n'
for var in $(cat $file)
do
   commands
done > text.txt
IFS=$IFS.OLD

...

for 循环用空格分隔单词,若有单词内包含',或者空格,可以用双引号把这个单词的所有内容括起来,或者为'符号转义

环境变量IFS定义了bash shell用作字符串分割符的一系列字符。默认情况下是空格,制表符,换行符。为了方便操作,可在脚本中手动设置IFS,来避免多种分隔符带来的不便。

while 循环

input="users.csv"
while IFS=',' read -r userid name #test commands#(也可以用[])
do
   echo "adding $userid"
   useradd -c "$name" -m $userid
done < "$input"

until循环,commands返回值为0时退出,和while相反

until test commands
do
   commands
done

break和continue不单单可以跳出当前循环,也可以通过break/continue + 数字来跳过外部循环

done 后加上 > file可以将循环输出重定向到文件

chapter 14 处理用户输入

$ + 数字,来获取命令行参数。./test1 1 2 3。可以用$1,$2,$3来获取,更多的,用$(10)这样的形式获取(这种形式也可以用来获取选项,如test.sh -a)

$0可以获取脚本名

$#可以获取脚本运行时携带的命令行参数个数

$*获取所有命令行参数作为一个字符串

$@获取所有命令行参数作为多个值,可用循环遍历

shift命令,将所有命令行参数向左移,最左(除了$0)被删除,这样用$1就能够遍历所有参数。也可以shift后加数字,代表移动多个单元

命令行选项和参数合用,使用 -- 字符分割

命令test16.sh -c test4 -a -b -- test1 test2 test3

#!/bin/bash

set -- $(getopt -q ab:cd "$@")
echo
while[ -n "$1" ]
do
   case "$1" in
      -a) echo "Found the -a option" ;;
      -b) echo "Found the -b option" ;;
      -c) param="$2"
          echo "Found the -c option"
          shift ;;
      --) shift
          break;;
       *) echo "$1 is not an option" ;;
   esac
   shift
done

count=1
for param in $@
do
   echo "Parameter #$count: $param"
   count=$[ $count + 1 ]
done

getopt处理合并选项

set命令的选项之一是 -- ,它会将命令行参数替换成set命令的命令行值。

该方法会将原始脚本的命令行参数传递给getopt命令,之后将getopt命令的输出传给set命令

但是getopt命令并不擅长处理带空格和引号的参数值。它会将空格作为分隔符而不是根据双引号将二者当作一个参数。

getopts命令则有改进

解析命令行时会移除开头的单破折线,并且可以处理带空格和引号的参数值

它有两个环境变量

OPTARG,选项跟的参数值

OPTIND,参数列表中getopts正在处理的参数位置

#!/bin/bash
echo
while getopts :ab:c opt
do
   case "$opt" in
      a) echo "Found the -a option" ;;
      b) echo "Found the -b option, with value $OPTARG" ;;
      c) echo "Found the -c option";;
      *) echo "Unknown option: $opt";;
   esac
done
shift $[ $OPTIND - 1 ]
echo
count=1
for param in "$@"
do
   echo "Parameter $count: $param"
   count=$[ $count + 1 ]
done

read命令从标准输入输出中接受输入,如(read -p "Enter your name: " first last)

-t 选项可以指定read命令等待输入的时间,时间超时则read返回非0退出状态码并且继续执行脚本

或者使用-n + 数字来指定read命令可接受最多的字符

-s选项可以避免输入数据显示在屏幕上,如输入密码的时候

从文件中读取数据

cat read | while read lind

chapter 15 呈现数据

文件描述符,0(STDIN),1(STDOUT),2(STDERR)

(shell对于错误消息的处理和普通输出是分开的,通过STDERR而不是STDOUT处理)

重定向错误信息到文件举例

ls  -al badfile 2> test4(这里的2代表STDERR,必须紧跟>)

如果想重定向错误和正常数据,必须用两个>

如 ls -al test test2 test3 badtest 2> test6 1> test7

如果想把脚本中的输出重定向到STDERR,那么需要加&

如 echo "This is an error" >&2

exec命令可以进行永久重定向

#!/bin/bash
exec 0< testfile
exec 2>testerror

echo "This is the start of the script"
echo "now redirecting all output to another location"

exec 1>testout

echo "This output should go to the testout file"
echo "but this should go to the testerror file" >&2

(尽管STDOUT被重定向了,但是echo仍可以发送给STDERR)

lsof可以列出整个linux系统打开的所有文件描述符

可以对null文件进行重定向来实现很多便利的操作

mktemp可以用来创建临时文件(mktemp testing.XXXXXX(六个X会被替换成6个字符来保证文件名不重复)),他的返回值是这个文件的名字,来方便在脚本中直接使用。

(-t,-d)

tee命令可以将STDIN过来的数据同时发往两处(date | tee -a testfile)

#!/bin/bash
outfile='members.sql'
IFS=','
while read lname fname address city state zip
do
   cat >> $outfile << EOF
   INSERT INTO members (lname,fname,address,city,state,zip) VALUES ('$lname','$fname','$address','$city','$state','$zip')
EOF
done < ${1}

chapter 16 控制脚本

trap命令:捕获信号

trap -- SIGINT删除捕获

可以使用后台模式运行脚本,在后台模式,进程运行不会和STDIN,STDOUT,STDERR关联,但是仍会使用中端显示器来显示STDOUT和STDERR消息,但是最好重定向,不然太混乱。

后台模式运行(./test.sh &,返回 [作业号] PID)

nohup命令可以让以后台模式运行的程序,在推出了终端会话后,仍然保持运行。(nohup ./test1.sh &)(脚本忽略关闭终端会话时发过来的SIGHUP信号)

jobs -l 命令查看作业运行情况

bg命令可以以后台模式重启作业

fg命令可以以前台模式重启作业

nice命令允许设置命令启动时的调度优先级,(-20(最高)到+19(最低))(nice -n 10 ./test4.sh > test4.out &)(普通系统用户只能把优先级调低,调高要用root)

renice命令更新当前进程的优先级

at命令可以在指定时间运行脚本

cron程序用来定期执行脚本(min hour dayofmonth month dayofweek command)(15 10 * * * command 每天10:15)

(15 16 * * 1 command 每周一16:15)(00 12 1 * * command 每个月第一天12:00)

(000 12 * * * if [`date +%d -d tomorrow` = 01 ] ; then ; command)(每个月最后一天)

(15 10 * * * /home/rich/test4.sh > test4out )

crontab来处理cron时间表

猜你喜欢

转载自blog.csdn.net/qq_40473204/article/details/113728762