Shell基础语法

shell不是面向对象语言

变量

shell中赋值的变量值全部为字符串,不存在数字类型

变量分类
全局变量 ≈ 环境变量
局部变量 ≈ 本地变量

赋值方法

变量名建议大写,等号两边不能有空格形式如下

变量名=变量值

VAR=10

取变量值

推荐使用 ${变量名} 获取变量值。
如果变量没有赋值,那么 $变量名 是一个空符串,容易引起语法错误,而 ${变量名} 不会引起语法错误。

$变量名 取变量的值
${变量名} 取变量的值
$((变量名)) 对变量执行算数运算
$[变量名] 对变量执行算数运算
$(命令) 或者 `命令` 取命令执行结果

导出变量
export

删除变量
unset

查看本地变量
set

查看全局变量
env



判别符

整数判别符

只能作用于整数

  • -eq=== 等于(equal)
  • -ne!= 不等于 (not equal)
  • -gt> 大于(great than)
  • -lt< 小于(less than)
  • -ge>= 大于等于(great equal)
  • -le<= 小于等于(less equal)
$ VAR=10
$ test $VAR -eq 10
$ echo $?
0

文件类型判别符

  • -d 目录文件
  • -f 普通文件 ( Linux中第一个属性为 [-] )
  • -p 管道
  • -l 软连接
  • -c 字符设备 ( 键盘,鼠标 )
  • -b 块设备( 硬盘 )
  • -s socket

字符串判别符

只能作用于字符串

  • [ -z string ] string长度为零则真
  • [ -n string ] string长度不为零则真
  • [ string1 = string2 ] 两个字符串相等为真
  • [ string1 != string2 ] 两个字符串不相等为真
bash-3.2$ VAR=tom
bash-3.2$ [ $VAR = tom ]
bash-3.2$ echo $?
0


条件判断

  • test 测试条件
  • [ 测试条件 ][[ 测试条件 ]] 两种写法分别对应bash与zsh语法,建议统一使用 [[ 测试条件 ]] 满足兼容
  • echo $? 用来查看上一条语句执行结果:0 表示正常结束,非 0 表示出现错误

逻辑运算符

尽量使用短路特性

  • [ !EXPR ] 逻辑非
  • [ EXPR1 -a EXPR2 ] 逻辑与 ( and )
  • [ EXPR1 -o EXPR2 ] 逻辑或 ( or )
bash-3.2$ VAR=10; VALUE=11
bash-3.2$ [ $VAR = 10 -a $VALUE = 11 ]
bash-3.2$ echo $?
0


条件分支

  • if / then / elif / else / fi
/ **
  * then 相当于 "{"
  * fi 相当于"}"
  */


#! /bin/bash

echo "Hello young man? Please answer boy or girl."
read BOY_OR_GIRL
if [ "$BOY_OR_GIRL" = boy ]; then
    echo 'Hello cowboy!'
elif [ "$BOY_OR_GIRL" = girl ]; then
    echo "Hello snow queen!"
else
    echo "Sorry, $BOY_OR_GIRL not recognized. Enter yes or no."
fi
  • case / esac
    Shell脚本的case可以匹配字符串和wildcard,每个匹配分支可以有若干条命令,末尾必须以 ;; 结束相当于break。esac相当于case语句结束符。
#! /bin/bash

echo "What's kind of beverage do you like: \n coca \n sprite \n tea"
read BEVERAGE

case "$BEVERAGE" in
  [cC][oO][cC][aA])
    echo "Here is your cocoa!";;
  [sS][pP][rR][iI][tT][eE])
    echo "Here is your sprite!";;
  [tT][eE][aA])
    echo "Here is your tea!";;
  *)
    echo "Sorry, $BEVERAGE is not available"
esac


循环

  • for / do / done

do 相当于 "{", done 相当于 "}"

#! /bin/bash
// 显示当前路径中所有文件信息
for file in `ls`; do
    if [ -f "$file" ]; then
        ls -l $file
    fi
done
  • while / do / done
#! /bin/bash
// 三次内输入正确密码
echo "Enter password:"
read PASWD
COUNT=1
while [ "$PASWD" != "secret" -a $COUNT -lt 3 ]; do
    echo "Sorry, try again"
    read PASWD
    COUNT=$(($COUNT+1))
done


位置参数

  • $0 脚本文件名,相当于 argv[0] 。当我们执行 bash a/b.sh 时,$0 的值是 a/b.sh
  • $1$2、…… 用来表示参数,$1 表示第一个参数,以此类推
  • $# 入参个数 argc - 1 ( 不包含 argv[0] )
  • $@ $* 入参列表 [$0, $1...]
  • $? 上一条命令的Exit status
  • $$ 获取当前进程号
  • shift 左移命令行参数


管道

  • | 把一个命令的输出传递给另一个命令做输入。
  • tee 把结果输出到标准输出的同时另一个副本输出到相应文件。
    文件重定向

[1] 0 标准输入 1 标准输出 2 标准出错

  • cmd > file 把标准输出重定向到file中
  • cmd >> file 追加的方法把标准输出重定向到file中
  • cmd > file 2>&1 把标准输出重定向到file中,同时将标准出错也重定向到file中[1]
  • cmd < file > file2 输入输出都重定向到file2中
  • cmd < &fd 把文件描述符 fd 作为标准输入
  • cmd > &fd 把文件描述符 fd 作为标准输出
  • cmd < &- 关闭标准输入


函数

函数没有返回值也没有参数列表

#! /bin/bash

foo() {
   for name in $@; do
       ls -l "$name"
   done
}

echo "-->start<--"
foo $@
echo "-->end<--"

函数传参

# 函数声明
foo () {
    # 函数体
}

# 函数调用以及传参
foo arg1 arg2 ...
#! /bin/bash

# 判断入参是否是文件
is_directory() {
    DIR_NAME=$1
    if [ ! -d "$DIR_NAME" ]; then
        return 1
    else
        return 0
    fi
}

# 批量创建目录
for DIR in $@; do
    if is_directory "$DIR"
        # : 表示真
        then : 
    else
        echo "$DIR not exist. Creating it now!"
        # 创建文件并将标准输出输出到”无底洞“,同时将标准错误输出到标准输出
        mkdir "$DIR" > /dev/null 2>&1
        # 判断 mkdir 命令执行结果,如果成功则输出提示语句
        if [ $? -ne 0 ]; then
            echo "Can not create directory $DIR!"
            exit 1
        fi
    fi
done


Shell脚本调试

  • -n 读一遍脚本中的命令但不执行,用于检测脚本中语法错误。
  • -v 一边执行脚本,一边将执行过的脚本命令打印到标准错误输出。
  • -x 将执行过的每一条命令和结果依次打印出来。( 使用频率高 )

使用方式

  1. 在命令行提供参数
sh -x ./myshell.sh
  1. shebang中指定,相当于全局设置全局调试
#! /bin/bash -x
  1. 在脚本中用 set 命令启动或禁用,方便局部设置局部调试
#! /bin/bash
if [ -z "$1" ]; then
  # 启动
  set -x
  echo "ERROR: Insufficient Args"
  exit 1
  # 取消
  set +x
fi
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355

推荐阅读更多精彩内容