深入Linux(五):Shell知识点

Shell

目录

shell书写规范

  • 参见谷歌shell风格指南 , 主要是推荐用"${var}"而不是$var
  • 应该在每个shellscript开头处加入下述信息:
#!bin/bash , 宣告这个scirpt 使用的shell名称,因为我们使用的是bash,所有以#!/bin/bash来宣告这个档案内的语法使用
# Program:
# This program shows "Hello World!" in your screen.
# History:
# 2005/08/23 Junfire First release
  • 在调用脚本的前面加上./ , 给变量赋值时不要加上空格, 例 str = "string" 是错误的,应该写成 str="string"
  • 如果字符串里包含空格就必须用引号把它们括起来,如果把一个$变量放在双引号里,会把变量替换为它的值,如果把一个$变量放在单引号里,则不会替换。
  • 在默认情况下, 所有变量都被看作字符串并以字符串来存储, 即使它们被赋值为数值时也是如此
  • 必须在[ ]符号和被检查的条件之间留出空格
  • 如果是想要用字符串比较必须加“", 例子 s="str" ; if [ $s ="str" ] 是错误的,应该写成 if [ "$s" ="str" ], 但如果是[[]] , 则双引号可有可无
[[ ]]优于 [ ]
  • [[ ]]结构比Bash版本的[ ]更通用。在[[和]]之间的所有的字符都不会被文件扩展或是标记分割,但是会有参数引用和命令替换。用[[ … ]]测试结构比用[ … ]更能防止脚本里的许多逻辑错误。比如说,&&,||,<和>操作符能在一个[[ ]]测试里通过,但在[]结构会发生错误
  • 如果要文件扩展功能,则只能使用[ ]

变量

  • 在shell里, 使用变量之前通常并不需要事先为它们做出声明。 你只是通过使用它们( 比如当你给它们赋初始值时) 来创建它们。 在默认情况下, 所有变量都被看作字符串并以字符串来存储, 即使它们被赋值为数值时也是如此。 shell和一些工具程序会在需要时把数值型字符串转换为对应的数值以对它们进行操作在shell中, 你可以通过在变量名前加一个$符号来访问它的内容。 无论何时你想要获取变量内容, 你都必须在它前面加一个$字符。你可以使用read命令将用户的输入赋值给一个变量。 这个命令需要一个参数, 即准备读入用户输入数据的变量名, 然后它会等待用户输入数据。
数组
  • 定义数组: 三种方式
    array_name=(value0 value1 value2 value3)
    
    array_name=(
    value0
    value1
    value2
    value3
    )
    
    array_name[0]=value0
    array_name[1]=value1
    array_name[n]=valuen
    
  • 读取数组元素: valuen=${array_name[n]}
  • 获取数组元素个数:length=${#array_name[@]} 或者 length=${#array_name[*]}
  • 取得数组单个元素的长度: lengthn=${#array_name[n]}
重要的$变量
$0当前脚本的文件名
$n传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
$#传递给脚本或函数的参数个数。
$*传递给脚本或函数的所有参数。
$@传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。
$?上个命令的退出状态,或函数的返回值。
$$当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。
# $* 和 $@ 的区别
# $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参# 数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

控制语句

if语句
  • if中条件为真返回0 , 条件为假返回非0 , 这与C是不一样的
  • 多个条件判断可用&& 和 ||, 这与C是一致的
for语句
while语句
until语句
  • 如果不满足until的条件,则do语句不会执行。先判断条件,满足情况下才执行do语句
case语句

函数

  • 函数内定义的变量也是全局变量,也就是说函数外可以访问, 如果要声明为局部变量,使用local关键字,示例:
local varName  
varName="string"   
或者 local varName="string"
  • 当一个函数被调用时, 脚本程序的位置参数( $*$@$#$1$2等) 会被替换为函数的参数。 这也是你读取传递给函数的参数的办法。 当函数执行完毕后, 这些参数会恢复为它们先前的值

命令

  • break 在控制条件未满足之前, 跳出for、 while或until循环,
  • continue 这个命令使for、 while或until循环跳到下一次循环继续执行。与C语言一致
  • :命令 冒号( :) 命令是一个空命令。 它偶尔会被用于简化条件逻辑, 相当于true的一个别名
  • . 命令 点( .) 命令用于在当前shell中执行命令 例子 ./shell_script
  • eval命令 eval命令允许你对参数进行求值,eval命令有点像一个额外的$, 它给出一个变量的值的值
  • exec命令 它的典型用法是将当前shell替换为一个不同的程序例 exec wall "thank for all the fish" 脚本中的这个命令会用wall命令替换当前的shell。 脚本程序中exec命令后面的代码都不会执行, 因为执行这个脚本的shell已经不存在了
  • exit n exit命令使脚本程序以退出码n结束运行
  • export命令: export将作为它参数的变量导出到子shell中, 并使之在子shell中有效。记住这一个定义就够了
  • expr命令:expr命令将它的参数当作一个表达式来求值 ,或者 后者更有效,可完成加减乘除取余运算
  • shift命令 shift命令把所有参数变量左移一个位置, 使$2变成$1$3变成$2, 以此类推。 原来$1的值将被丢弃, 而$0仍将保持不变
  • set命令
  • printf命令
  • return:return命令的作用是使函数返回
  • trap命令 用于指定在接收到信号后将要釆取的行动,trap命令有两个参数, 第一个参数是接收到指定信号时将要釆取的行动, 第二个参数是要处理的信号名。trap command signal
    • 如果要重置某个信号的处理方式到其默认值, 只需将command设置为-。 如果要忽略某个信号, 就把command设置为空字符串''
  • unset命令的作用是从环境中删除变量或函数

获取命令执行结果

  • 编写脚本程序时, 你经常需要捕获一条命令的执行结果, 并把它用在shell脚本程序中。 也就是说, 你想要执行一条命令, 并把该命令的输出放到一个变量中。这可通过$(command)语法来实现, 也可以用一种比较老的语法形式 `command`(注意是反引号), 这种用法目前依然很常见 。推荐用前者
  • 算术扩展:expr命令可以处理一些简单的算术命令,一种更新更好的办法是使用$((...))扩展。 把你准备求值的表达式括在$((...))中能够更有效地完成简单的算术运算 例子 x=0, x=$(($x+1))

参数扩展

在这里插入图片描述

  • 示例{foo#*/}语句仅仅匹配并删除最左边的/(记住, *匹配零个或多个字符) 。{foo##*/}语句匹配并删除尽可能多的字符, 所以它删除最右边的/及其前面的所有字符

here文档

  • 在shell脚本程序中向一条命令传递输入的一种特殊方法是使用here文档。 它允许一条命令在获得输入数据时就好像是在读取一个文件或键盘一样, 而实际上是从脚本程序中得到输入数据。here文档以两个连续的小于号<<开始, 紧跟着一个特殊的字符序列, 该序列将在文档的结尾处再次出现。
  • 写块注释时,可以使用该方法

调试脚本程序

在这里插入图片描述

附录:条件判断

  • 注意如果是想要用字符串比较必须加"", 例子 s="str" if[ $s ="str" ] 是错误的,应该写成 if[ "$s" ="str" ]

在这里插入图片描述


一个shell程序例子

#!/bin/bash
#program:
   #function :save and fetch and list goods
   #save save goods name, if exists , won't saved again
   #fetch fetch goods and delete it from datasets
   #list 为查看所有已存储的物品
   #物品均已字符串形式存放
#history
   #2016.9.3 first commit
title_file="title.txt"
temp_file=/tmp/cdb.$$
menu_choice=""
trap 'rm -f $temp_file' EXIT #trap命令用于设置在用户按下Ctrl+C组合键时的中断处理
set_menu_choice(){
  echo "Main Menu:"
  echo " a) save"
  echo " b) fetch"
  echo " c) list"
  echo " q) quit"
  echo
  read menu_choice
  return
}
get_return(){
  read -p "press any key to continue, but q for exit: " x
  if [ "$x" = "q" ]; then
    exit 0
  fi
  return 0 
}
save(){
  read -p "please input the name of goods you want to save: " name
  if grep -q $name $title_file ; then
     echo "already exist"
  else
     echo $name >> $title_file
     echo "saved"
  fi
  get_return
}
fetch(){
  read -p "please input the name of goods you want to find: " name
  if grep -q $name $title_file; then
    grep -v "$name" $title_file > $temp_file
    mv $temp_file $title_file
    echo "fetched" 
  else
    echo "Sorry, goods don't exist"
  fi
  get_return
}
list(){
  echo 
  cat $title_file
  echo
  get_return
}
rm -f $temp_file
if [ ! -f $temp_file ]; then
 touch $temp_file
fi
if [ ! -f $title_file ] ; then
 touch $title_file
fi
clear # clear the terminal screen
sleep 1
quit=n
while [ "$quit" != "y" ] ;
do
  set_menu_choice
  case "$menu_choice" in
      a) save ;;
      b) fetch ;;
      c) list ;;
      q | Q) quit=y;;
      *) echo "Sorry , choice not recognized"
  esac
done
rm -f $temp_file
echo "Finished"
exit 0
# shell脚本收藏

#batch rename
i=0; for img in `ls *.jpg`; do mv $img test-`printf %04d $i`.png; i=`expr $i + 1`; done
#!/bin/bash
echo $*
#第一个冒号表示忽略错误;字符后面的冒号表示该选项必须有自己的参数
#在getopts分析选项时,如果-a后面不带参数,直接跟-b的话,那么-b将作为-a的参数。
while getopts ":a:bc" opt
do
        case $opt in
                a ) echo "a $OPTARG $OPTIND" ;;
                b ) echo "b $OPTIND";;
                c ) echo "c $OPTIND";;
                ? ) echo "error"
                    exit 1;;
        esac
done
echo $OPTIND
shift $(($OPTIND - 1))
#通过shift $(($OPTIND - 1))的处理,$*中就只保留了除去选项内容的参数,可以在其后进行正常的shell编程处理了。
echo $0
echo $*
  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值