shell

本文介绍了Shell编程的基础知识,包括数据类型与变量、分支和循环语句、条件测试、函数、脚本调试,以及常用的正则表达式和工具如grep、find、sed和awk。特别强调了在条件测试中的逻辑运算和脚本调试方法。
  • 数据类型、变量
  • 分支语句、循环语句
  • 函数

数据类型、变量

  • shell中仅有一种数据类型:字符串
  • 变量类型仅有两种:环境变量、本地变量
VAR=123 #定义一个本地变量VAR,值123(字符串)
export VAR #把VAR导出为环境变量
//上述两步可合并为一步:
export VAR=123
//除了 echo $VAR 外,还可以用如下方式查看该环境变量的值:
env | grep VAR
  • 自建一个命令别名:alias,比如:
alias pg='ps aux | grep'
pg init #等同于 ps aux | grep init
  • 删除一个变量:unset
  • 通配符(wildcard):
    *:匹配0个或多个任意字符
    ?:匹配一个任意字符
    [若干字符]:匹配方括号中任意一个字符的一次出现
  • 命令代换:显示命令本来的功能而不是作为一个字符串显示出来
  1. 反引号 ``
var=`date`
echo $var //执行date命令
  1. $( ):
var=$(ls)
echo $var //执行ls命令
  • 算术代换:
VAR=1
echo $[VAR+3] //4

echo $[2#10+8#76] //2进制10加8进制76,结果为64
  • 转义字符:
    反斜杠\:续行;转义
touch \$\ \$test.sh //创建一个名为’$ $test.sh’的新文件

touch ./-abc //创建一个名为’-abc’的新文件,或:touch -- -abc
rm ./-abc //删除该文件,或:rm -- -abc
  • 单、双引号:
  1. 单双引号可嵌套使用:
echo 'hello "xiao"' //hello "xiao"
echo "hello 'xiao'" //hello 'xiao'
  1. 双引号:被双引号用括住的内容,将被视为单一字串,它防止通配符扩展,但允许变量扩展。这点与单引号不同。例如:
VAR=`date`
echo '$VAR' //$VAR
echo "$VAR" //执行date命令的结果
  1. 注意:
var= //定义变量var,初值为Null,常用于if条件判断语句中
echo ‘$var’ //$var
echo “$var” //为空,即Null
//区别于:
var=Null //定义变量var,初值为字符串Null

语句

条件测试

  • test、[
    [ -d DIR ] 如果DIR存在并且是一个目录则为真
    [ -f FILE ] 如果FILE存在且是一个普通文件则为真
    [ -z STRING ] 如果STRING的长度为零则为真
    [ -n STRING ] 如果STRING的长度非零则为真
    [ STRING1 = STRING2 ] 如果两个字符串相同则为真
    [ STRING1 != STRING2 ] 如果字符串不相同则为真
    [ ARG1 OP ARG2 ] ARG1和ARG2应该是整数或者取值为整数的变量,OP是-eq(等于)-ne(不等于)-
    lt(小于)-le(小于等于)-gt(大于)-ge(大于等于)之中的一个
    例如:
var=10
test $var -gt 20 //gt: greater than
echo $? //1,表示上述比较结果为假;echo $? //输出上一条命令的返回值
[ $var -lt 20 ] //lt: less than
echo $? //0,表示上述比较结果为真
  • 测试条件之间还可以做与、或、非逻辑运算:
    [ ! EXPR ] EXPR可以是上表中的任意一种测试条件,!表示逻辑反;
    [ EXPR1 -a EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-a表示逻辑与;
    [ EXPR1 -o EXPR2 ] EXPR1和EXPR2可以是上表中的任意一种测试条件,-o表示逻辑或。
var=abc
[ -d Desktop -a $var = 'abc' ] //Desktop是否是一个目录,并且,var的值是否等于abc
echo $? //0,真
  • 建议:应总是把变量取值放在双引号之中,这是一种好的shell编程习惯。所以上述例子中,作为一种好习惯,应写为:
[ -d Desktop -a "$var" = 'abc' ]

因为,如果上例中的$var变量事先没有定义,则被Shell展开为空字符串,会造成测试条件的语法错误(展开为[ -d Desktop -a = ‘abc’ ])。

分支

  • if语句:
    例如:
#! /bin/sh

echo "Is it morning? Please answer yes or no."
read var 
if [ "$var" = "yes" ]; then
        echo "Good morning!"
elif [ "$var" = "no" ]; then
        echo "Good afternoon!"
else
        echo "Sorry, $var not recognized. Enter yes or no."
fi

注意:

if :
then
	echo "always true"
fi

其中,if : 中的冒号表示条件总是为真

  • case语句:
#! /bin/sh

echo "enter YES or NO"
read var 

case "$var" in
        YES|Yes|Y|yes|y)
                echo "good!"
                ;; #similar to break in C\C++
        [nN]*) #a string beginning with n or N
                echo "bad!"
                ;;
        *) #similar to default
                echo "invalid input! enter YES or NO please."
                ;;
esac
echo "will return"
return 0

循环

  • for-do-done
#! /bin/bash

for MYFILE in $(ls); do
        printf "$MYFILE "

        if [ -d "$MYFILE" ]; then
                echo "it's a directory."
        elif [ -f "$MYFILE" ]; then
                echo "it's a file."
        else
                echo "others."
        fi

done
  • while-do-done
#! /bin/bash

count=2

echo "Please enter the password: "
read psd 

while [ $psd != "myword" -a $count -gt 0 ]; do
        count=$[count-1]
        echo "wrong! enter again:"
        read psd 
done

if [ $psd = "myword" ]; then
        echo "good!"
fi

if [ $count -eq 0 ]; then
        echo "you have entered wrong password three times."
fi
  • break
    和C语言中的不同之处在于,break[n]可以指定跳出n层循环。
  • continue:同C语言中用法

特殊变量

$0 相当于C语言main函数的argv[0],表示当前进程名
$1、$2... 这些称为位置参数(Positional Parameter),相当于C语言main函数的argv[1]、argv[2]...
$# 相当于C语言main函数的argc - 1,即去掉函数名的参数个数,注意这里的#后面不表示注释
$@ 表示参数列表"$1" "$2" ...,例如可以用在for循环中的in后面。
$* 表示参数列表"$1" "$2" ...,同上
$? 上一条命令的Exit Status
$$ 当前进程号

输入输出

  • echo
echo [option] string
-e 解析转义字符
-n 不回车换行。默认情况echo回显的内容后面跟一个回车换行。
echo "hello\n\n"
echo -e "hello\n\n"
echo "hello"
echo -n "hello"
  • 管道|
  • tee
    tee命令把结果输出到标准输出,另一个副本输出到相应文件。
  • 文件重定向
cmd > file 2>&1 //标准出错也重定向到1所指向的file里
cmd < file1 > file2 //输入输出都定向到文件里

函数

  • 注意位置参数在函数内外的区别:
#! /bin/bash

echo $1 //命令行输入的第一个参数
echo $2
echo $3

func() {
        echo $1 //该函数被调用时紧跟着的第一个参数
        echo $2
        echo $3
}

echo -e "---func start---\n"
func 1 2 3 
echo -e "---func end---\n"

//执行:
chmod a+x funcdemo.sh
funcdemo.sh a b c
//执行结果:
a
b
c
---func start---

1
2
3
---func end---

//注意:位置参数$1、$2、...位于函数外则表示从命令行接收的参数;
//位于函数内则表示函数被调用时紧跟着的参数
//$0在函数内外没有区别,均表示当前进程名
  • 另一个例子:
#输入一些命令行参数代表文件名,如果不存在则创建这些文件
#! /bin/bash

is_file() {
        FILE_NAME=$1
        if [ ! -f $FILE_NAME ]; then
                return 1
        else
                return 0
        fi
}

for file in "$@"; do

        if is_file "$file" #is_file 返回0表示真,返回1表示假
        then : #do nothing
        else
                echo "$file doesn't exist. Creating it now..."
                touch $file > /dev/null 2>&1
                if [ $? -ne 0 ]; then
                        echo "Can't create file $file"
                        exit 1
                fi
        fi

done

脚本调试

  • -n
    读一遍脚本中的命令但不执行,用于检查脚本中的语法错误
  • -v
    一边执行脚本,一边将执行过的脚本命令打印到标准错误输出
  • -x
    提供跟踪执行信息,将执行的每一条命令和结果依次打印出来
  • 使用方法有三种:
  1. 在命令行提供参数
$ sh -x ./script.sh
  1. 在脚本开头提供参数
#! /bin/sh -x
  1. 在脚本中用set命令启用或禁用参数
#! /bin/sh

if [ -z "$1" ]; then
	set -x
	echo "ERROR: Insufficient Args."
	exit 1
	set +x
fi

正则表达式

常用工具

grep

  • grep侧重于过滤文件中的内容,而find侧重于根据文件名、文件类型、文件修改时间来找文件。
  • grep、egrep

find

sed

awk

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值