shell脚本语言编程

来源:互联网 发布:团队协作工具linux 编辑:程序博客网 时间:2024/06/13 03:54
#Shell既是一种命令语言,又是一种程序设计语言,作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支


#--------------shell 变量-------------------
#变量名和等号之间不能有空格
 #首个字符必须为字母(a-z,A-Z)。
#中间不能有空格,可以使用下划线(_)。
#不能使用标点符号。
#不能使用bash里的关键字(可用help命令查看保留关键字)
#使用一个定义过的变量,只要在变量名前面加美元符号($)即可,变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界
#使用 readonly 命令可以将变量定义为只读变量
#使用 unset 命令可以删除变量


#$0 当前脚本的文件名  $n 传递给脚本或函数的参数   $# 传递给脚本或函数的参数个数   $*/$@ 传递给脚本或函数的所有参数    $? 上个命令的退出状态,或函数的返回值  $$ 当前Shell进程ID
#$* 和 $@ 的区别:但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数
#\\ 反斜杠     \b 退格(删除键)  \n 换行   \r 回车   \t 水平制表符(tab键)  \v 垂直制表符


#变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值
#${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值    ${var:=word}如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word    ${var:+word}如果变量 var 被定义,那么返回 word,但不改变 var 的值
# ${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。若此替换出现在Shell脚本中,那么脚本将停止运


#命令替换的语法:`command`
#--------------shell 变量-------------------

#!/bin/bash


echo "what is your name?"
read P
echo "Hello,$P"


#运算符
#1.expr能完成表达式的求值操作,表达式和运算符之间要有空格,比如2 + 2,完整的表达式要被` `包含 ,变量与=之间不能有空格,乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
a=10
b=20


val=`expr $a + $b`                     
echo "a + b: $val"


val=`expr $a - $b`
echo "a - b : $val"


val=`expr $a \* $b`
echo  "a * b: $val"


val=`expr $a / $b`
echo "a / b : $val"


val=`expr $b % $a`
echo "b % a : $val"


#条件表达式要放在方括号之间,并且要有空格,例如 [$a==$b] 是错误的,必须写成 [ $a == $b ]
if [ $a == $b ]
then
  echo "a is equal to b"
 fi
 
 if [ $a !=  $b ]
 then
   echo "a is not equal to b"
  fi
  
  
  #关系运算符
  #只支持数字,不支持字符串,除非字符串的值是数字。
  #-eq 检测两个数是否相等,相等返回true.   -ne检测两个数是否相等,不相等返回true.    -gt或-ge检测左边数是否大于右边  -lt或-le检测左边数是否小于右边
  if [ $a -eq $b ]
  then
  echo "true"
  else
  echo "false"
  fi
  
  # !非运算,[!false]返回true,   -o或运算,有一个为true,则返回true,   -a与运算,两个都为true,才返回true
  if [ $a -lt 100 -a $b -gt 15 ]
  then 
  echo "true"
  else
  echo "false"
  fi
  
  #字符串运算符
  # -z 检测字符串长度是否为0,为0返回 true. -n检测字符串长度是否为0,不为0返回 true. str检测字符串长度是否为空,不为空返回true.
  c="abc"
  d="def"
  if [ -z $a -a -z $b ]
  then 
  echo "ture"
  else
  echo "false"
  fi


#文件测试运算符
# -b(块设备文件,是则返回true).-c(字符设备文件.是则返回true).-d(是否是目录,是则返回true). -f(普通文件).-g(是否设置SGID位).-k(是否设置粘着位).
# -p(是否具名管道).-u(是否设置SUID位).-r(是否可读),-w(是否可写).-x(是否可执行).-s(是否为空.文件大小是否大于0,不为空返回true).-e(文件(包括目录)是否存在)
file="/F/work_sources/study_resources/shell.sh"
if [ -r $file ]
then echo "read"
else echo "not read"
fi


#shell注释  可以把要注释的代码用一对花括号括起来,定义成函数.


#shell字符串可以用单引号,也可以用双引号,也可以不用引号.
#单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的.单引号字串中不能出现单引号(对单引号使用转义符后也不行)
#双引号里可以有变量.双引号里可以出现转义字符
name="xx"
str="hello,i know you are\"$name\"! "
echo $str


#获取字符串长度
string="avsss"
echo ${#string}


#提取字符串
string="ali is a great company"
echo ${string:1:10}


#查找子字符串
string="ali is a great company"
echo `expr index "$string" is`


#数组
#bash支持一维数组(不支持多维数组).Shell中,用括号来表示数组,数组元素用“空格”符号分割开
array_name=(value0 value1 value2 value3)
#读取数组,使用@ 或 * 可以获取数组中的所有元素
echo ${array_name[2]}
#获取数组的长度
echo "length=${#array_name[*]}“
echo "length=${#array_name[@]}"


#echo命令
#双引号可有可无,单引号主要用在原样输出中, 换行(\n),不换行(\c)
echo `date`
#显示结果重定向至文件     echo "It is a test" > myfile                 若需要原样输出字符串(不进行转义),请使用单引号     echo '$name\"'


#printf 命令用于格式化输出, 是echo命令的增强版,printf 不像 echo 那样会自动换行,必须显式添加换行符(\n)             printf 命令的语法:printf  format-string  [arguments...]format-string 为格式控制字符串,arguments 为参数列表
printf "hello!\n"


#
    if ..then. fi 语句;
    if ..then. else .then.. fi 语句;
    if ..then. elif .then.. else .then.. fi 语句。


# test 命令用于检查某个条件是否成立,与方括号([ ])类似。
    if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;


 function file(){
option="${1}"
case ${option} in
   -f) FILE="${2}"
      echo "File name is $FILE"
      ;;
   -d) DIR="${2}"
      echo "Dir name is $DIR"
      ;;
   *) 
      echo "`basename ${0}`:usage: [-f file] | [-d directory]"
      exit 1 # Command to come out of the program with status 1   
      ;;
esac
}


function  about(){
case 值 in
模式1)
    command1
    command2
    command3
    ;;
模式2)
    command1
    command2
    command3
    ;;
*)
    command1
    command2
    command3
    ;;
esac




for循环一般格式为:
for 变量 in 列表      列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量,in 列表是可选的,如果不用它,for 循环使用命令行的位置参数
do
    command1
    command2
    ...
    commandN
done


显示主目录下以 .bash 开头的文件:


for FILE in $HOME/.bash*
do
   echo $FILE
done


while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为:


while 判断条件
do
   Statement
done
}
 #while循环可用于读取键盘信息。下面的例子中,输入信息被设置为变量FILM,按<Ctrl-D>结束循环 
echo 'type <CTRL-D> to terminate'
echo -n 'enter your most liked film: '
while read FILM
do
    echo "Yeah! great film the $FILM"
done    

#until 循环执行一系列命令直至条件为 true 时停止
a=0
until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done


#shell 跳出循环 
#break命令允许跳出所有循环(终止执行后面的所有循环).在嵌套循环中,break 命令后面还可以跟一个整数,表示跳出第几层循环
#continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环,continue 后面也可以跟一个数字,表示跳出第几层循环


#Shell 函数的定义格式
#function_name(){}       函数返回值,可以显式增加return语句;如果不加,会将最后一条命令运行结果作为返回值.Shell 函数返回值只能是整数,一般用来表示函数执行成功与否,0表示成功,其他值表示失败
# Define your function here
Hello () {
   echo "Url is http://see.xidian.edu.cn/cpp/shell/"
}
# Invoke your function
#Hello     调用函数只需要给出函数名,不需要加括号
#unset .f function_name   删除函数也可以使用 unset 命令,不过要加上 .f 选项
#如果你希望直接从终端调用函数,可以将函数定义在主目录下的 .profile 文件,这样每次登录后,在命令提示符后面输入函数名字就可以立即调用


在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数.
#注意,$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数
funWithParam(){
    echo "The value of the first parameter is $1 !"
    echo "The value of the second parameter is $2 !"
    echo "The value of the tenth parameter is $10 !"
    echo "The value of the tenth parameter is ${10} !"
    echo "The value of the eleventh parameter is ${11} !"
    echo "The amount of the parameters is $# !"  # 参数个数
    echo "The string of the parameters is $* !"  # 传递给函数的所有参数
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73


#  $# 传递给函数的参数个数。 $* 显示所有传递给函数的参数。 $? 函数的返回值.




#Shell  输入输出重定向
     #注意:输出重定向是大于号(>),输入重定向是小于号(<)
     #命令的输出不仅可以是显示器,还可以很容易的转移到文件,这被称为输出重定向
     #command > file   (输出到显示器的内容就可以被重定向到文件) 如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾
     for i in 1 2 3
     do
     echo "$i">>test.txt
     done


#一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:
 #标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  #标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  #标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。
  #默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file
    #   $command > file 2>&1    (stdout 和 stderr 合并后重定向到 file)       $command < file1 >file2  (对 stdin 和 stdout 都重定向)
    # n >& m 将输出文件 m 和 n 合并。
    # n <& m 将输入文件 m 和 n 合并。
    # << tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
    
    #  wc -l 命令计算 document 的行数
    #Here Document "嵌入文档" ,是 Shell 中的一种特殊的重定向方式
cat << EOF
This is a simple lookup program
for good (and bad) restaurants
in Cape Town.
EOF


 # command > /dev/null      (/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出“的效果。)




#Shell 也可以包含外部脚本,将外部脚本的内容合并到当前脚本
#可以使用 . filename 或source filename     一般使用点号(.),但是注意点号(.)和文件名中间有一空格   注意:被包含脚本不需要有执行权限


#touch命令主要用来修改文件时间戳,或者新建一个不存在的文件




#sed命令(sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作)
     #sed命令行格式为:     sed [-nefri] ‘command’ 输入文本  
     sed(){
-i:直接修改源文件  sed -i 's/123/234/' test.sh   将文件 test.sh内出现的“123”替换为“234”
-e:多次编辑  sed -i -e 's/123/234/g' -i -e '7 s/^/#/' test.sh  先将所有的123替换为234,再将第7行前加#号注释
-f:指定sed脚本文件名
-n:取消默认的输出,用sed不加任何选项的话你会看到所有内容输出,并不是按照sed命令所限制的条件输出
sed -n '2p' test.txt  显示第2行的内容   sed -n '1p' test.txt 第一行   sed -n '$p' test.txt 最后一行
sed -n '1,3'p test.txt 显示第1到3行的内容
sed -n '/val/'p test.txt 仅显示包含“val”字符的行
sed -n '/\$/'p test.txt 显示包含"$"字符的行
sed -n '/[0-9]$/'p test.txt 显示以数字结尾的行,[0-9]是正则表达式 代表数字0到9;"$"表示行尾(“^”表示行首)
sed -n -e '/^T/'p -e '/[0-9]$/'p test.txt 显示以数字结尾的行并显示以大写T为开头的行
sed -n '/.*ing/'p test.txt 显示含“ing”的行
sed -n 's/nurse/little &/p' test.txt  将“nurse”改为“little nurse”,“&”命令用来重新调用被替换的内容
sed 's/--*//g' | sed '/^$/d' | sed '$d' | sed '1d' | awk '{print $1}' 使用s/--*//g删除横线-------     使用/^$/d删除空行 使用$d删除最后一行 使用1d删除第一行      awk {print $1}打印第一列
sed -i -e 's/^/#&/' test.txt 给每行行首加上“#”注释
}
 
#‘grep’是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来
grep(){
结合使用"^$"查询空行
\< 和 \> 分别标注单词的开始与结尾
-c   只输出匹配行的计数
-i   不区分大小写
-h   查询多文件时不显示文件名
-l   只列出匹配的文件名
 -L 列出不匹配的文件名
-n   显示匹配行及行号
-v   反向选择,显示不包含匹配文本的所有行
-w 只匹配整个单词
-r     递归搜索,不仅搜索当前工作目录,而且搜索子目录
--color=auto :可以将找到的关键词部分加上颜色的显示喔!(在 ~/.bashrc 内加上这行:alias grep='grep --color=auto'再以『source ~/.bashrc 来立即生效, 这样每次运行 grep 他都会自动帮你加上颜色显示啦)
 grep -l -r ‘energywise’ * #在当前目录及其子目录下搜索'energywise'行的文件,但是不显示匹配的行,只显示匹配的文件
}
 
readlink (){
readlink -f  判断执行文件的类型,如果是一个符号链接,得到这个链接的目的路径
}
xargs(){
管道符后不加xargs相当于先将管道后面的命令回车执行一下,再从键盘里输入管道符前面命令执行的结果内容;加上xargs 相当于直接从键盘输入管道符前面命令执行的结果内容再回车
}

tr命令可以对来自标准输入的字符进行替换、压缩和删除

原创粉丝点击