Linux Basics-shell

Linux Basics-shell

          learn shell and scripts

shell是怎么解释命令的运行?

shell到底是怎么解释命令的,它的运行机制是什么

第一行的#!

#!的读音是shabang,他的完整意义是sharp bang
#读作sharp 比如c# 注意这个一开始的含义是音乐上用来记载上升半音的 . c#就是取其意(比c语言更好), 第二个符号是!,!读作bang,是以前UNIX程序员对于这个符号的读法,比如linux中对于历史命令中的上一个命令的快捷键就是!!(读作bangbang,好像开枪的声音)

#!是位于shell脚本中的第一行的开头,他对于shell来讲有特殊的意义,当一个文件的开头是#!的时候,内核会扫描该行其余部分,看是否存在有可有的执行程序解释器路径,还会看是否有选项传递给解释器,一般后面是/bin/bash,用bash解释器解释下面语句.

特殊文件/dev/null和/dev/tty

/dev/null 被称作bit bucket 就是大家所俗称的输出字节垃圾桶,传送到这里的数据都被会丢掉

/dev/tty 当打开这个文件,linux会重新把它定向到一个终端,在与程序结合,读取人工输入的时候有用,比如

printf "Enter new password: " #提示输入
stty -echo     #关闭自动打印输入字符功能
read pass < /dev/tty       #读取密码
printf "Enter again: "    #提示再输入一次
read pass2 < /dev/tty    #再读取一次输入的密码
stty echo         #打开自动打印输入字符功能
...

stty命令用来控制终端,-echo用来关闭自动打印输入字符功能

shell查找外部是按照$PATH来查找的,如果要把自己编写的脚本让shell找到,可以把他放到path路径中,比如

cd #切换目录
mkdir bin #建立bin目录
mv yourshellscripts bin #移动你的脚本到bin中去
PATH=$PATH:$HOME/bin #添加脚本到path路径中去
yourshellscripts #运行它

shell脚本参数

位置参数(positional parameters)指的是shell脚本命令行参数(commend arguments),位置不能超过9,超过9之后得用花括号把他括起来

echo first arg is $1
echo tenth arg is ${10}

$符号用来引用一个变量的值,其实正确的变量引用是像上例中直接引用10一样的写法,用美元符号后面跟着花括号括起来的值,不过我们一般情况下省略了.

执行顺序

我们站在另外一个角度去看shell是怎么执行命令的,他内部是怎么个运行过程.

shell从标准输入或者脚本中读取的每一行称为管道(pipeline),它包含了许多的命令(commend)

命令的分隔:
命令的分隔用特殊符号来做
分号( ; ) ,管道( | ) & 逻辑AND( && ) 逻辑OR( || )

每读取一个管道,shell会将命令分隔,对命令做如下操作
1. 用固定的meta字符将命令分成token, 这些meta字符,比如空格,tab字符,换行符,分号,逗号,重定向符号,管道符号和&符号
2. 检查每个命令的第一个token,看看它是不是不带反斜杠或者引号的关键字(keyword),如果他是一个开放的关键字(if与其他控制结构的开始符号,如 { 或者 ( ) ,则这个命令其实是一个符号命令(compound commend).shell为符号命令进行内部设置,读取下一条命令,并再次启动进程,如果关键字非复合命令的开始符号(比如它是控制语句的中间部分,比如else,then,do)或者是结尾部分比如fi,done等),则shell发出语法错误的信息
3. 将每个命令的第一个单词与别名(alia)列表对照检查.如果匹配,则代替别名的定义,并回到步骤1;否则进程步骤4
4. 如果波浪号( ~ )字符出现在单词的开头,则将其替换成用户的家目录
5. 将任何开头是 ,()6. (string)或者`strin`的表达式,执行命令替换
7. 执行形式 ((string))8.,,,使 IFS里面的字符作为定界符,而不是步骤1中的meta字符
9. 对于* ? 以及一对[…]的任何出现次数,都执行文件名生成(filename generation)的操作,也就是通配符展开
10. 使用第一个单词作为第一个命令,遵循次序查找,这个次序是:特殊内建命令—–>函数—–>一般内建命令—–>$PATH从左到右找到的第一个文件
11. 在完成io重定向与其他同类型事项之后,执行命令

具体流程请看下图

Alt text

如果你不明白上面所说,下面我举个例子
mkdir /tmp/x #建立临时目录
cd /tmp/x  #切换到刚刚建立的临时目录
touch f1 f2 #创建文件f1 f2
f=f y="a b" #变量赋值
echo ~+/\${f}[12] \$y \$(echo cmd subst) \$((3 + 2 )) >out

上面的命令执行步骤如下
1. shell分隔token, io重定向>out是被识别而且被存储起来
处理完成的token如下,每个token显示在命令行下,用不同颜色表示顺序依次是: 红色token1,绿色token2,紫色token3,蓝色token4,黄色token5:

echo ~+/${f}[12] $y $(echo cmd subst) $((3 + 2 ))
2. 检查第一个单词(echo)是否是关键字,例如if 或者 for 这里不是,所以不变
3. 检查第一个单词(echo)是否有别名,这里不是,所以命令不变
4. 扫描所以单词是否需要波浪号展开,这里token2(绿色部分),就被修改,处理结果如下:
echo /tmp/x/${f}[12] $y $(echo cmd subst) $((3 + 2 ))
5. 下一步变量展开,token2和3都被修改,结果如下:
echo /tmp/x/${f}[12] a b $(echo cmd subst) $((3 + 2 ))
6. 下面是命令替换,token4于是被修改,结果如下:
echo /tmp/x/${f}[12] a b cmd subst $((3 + 2 ))
7. 执行算术替换,修改token5,结果如下;
echo /tmp/x/${f}[12] a b cmd subst 5
8. 前面所有的展开产生的结果,都将被再一次扫描看是否有$IFS,如果有将他们作为分隔符,产生额外的单词,比如原来的$y原来是组成一个单词,但是展开式”a-空格-b”,再次阶段被分为2个单词,相同命令也被用于命令替换$(echo cmd subst)的结果上,先去token3 变成了token3和4,先去的token4变成token5和6,结果如下(每种颜色代表一个token):
echo /tmp/x/${f}[12] a b cmd subst 5
9. 通配符展开,token2展开成为2和3,结果如下:
echo /tmp/x/f1 /tmp/x/f2 a b cmd subst 5
10. 这个时候shell会寻找echo命令,echo是个内建命令
11. shell执行命令,首先执行>out的io重定向,再调用内部的echo
12. 最后shell显示

/tmp/x/f1 /tmp/x/f2 a b cmd subst 5
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值