bash的工作特性之命令执行状态返回值和命令展开所涉及内容

bash的工作特性之命令执行状态返回值

一、shell是什么?

Shell本身是一个用C语言编写的程序,它是用户使用Unix/Linux的桥,用户的大部分工作都是通过Shell完成的。Shell既是一种命令语言,又是一种程序设计语言。作为命令语言,它交互式地解释和执行用户输入的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。
shell是一个应用程序,是用户管理应用程序的一个接口。

二、广义上shell的分类

GUI:图形用户界面
KDE,GNOME,XFCE
CLI:命令行接口
bash, zsh, fishsh, csh, tcsh, ksh

在大多发行版中常用的为bash

三、bash的特性

bash是弱类型的编程语言,不严格区分数据类型,意味把所有数据统统当作字符串处理;

字符串类型的数据可不加引号;

引号有三种类型:', ", `

', ":字符引用

': 强引用,其内部的变量不会被替换;

":弱引用,其内部的变量会被替换;

`:命令引用

变量引用:${NAME}

a、bash特性之一:命令别名

获取当前用户可用的别名的定义:

1  # alias
定义别名:

1  # alias NAME='COMMAND'
生命周期:当前shell进程;

1 # unalias NAME
撤消别名:

b、bash的特性之二:命令历史

shell进程会保存其会话中用户曾经执行过的命令;命令通过其“历史文件”来持久保存此前执行过的命令;每个用户都有其自己专用的历史文件;

HISTSIZE:shell进程的缓冲区保留的历史命令的条数;

HISTFILESIZE:命令历史文件可保存的历史命令的条数;

默认均为1000;

1 # echo $HISTSIZE
2 1000
3 # echo $HISTFILESIZE
4 1000
HISTFILE:当前用户的命令历史文件;

~/.bash_history

查看命令历史列表:

1 # history
命令用法:

history -c:清空命令历史;

history -d OFFSET:删除指定的条目;

1 # history -d 156
-a 将当前缓冲的历史行追加到历史文件中

-n 从历史文件中读取所有未被读取的行

-r 读取历史文件并将内容追加到历史列表中

调用命令历史列表中的命令以重执行之目的:

!#:再一次执行历史列表中的第#条命令;

1 # history
2 ....
3 72 cat test
4 73 history
5 # !72
6 cat test
7 Hello World
!!:再一次执行上一条命令;

1 # cat test
2 Hello World
3 # !!
4 cat test
5 Hello World

        !STRING:再一次执行命令历史列表中最近一个以指定的STRING开头的命令;

1 # !cat
2 cat test
3 Hello World
调用上一条命令的最后一个参数:

快捷键:ESC, .
Alt+.

!$:给出的字符组合

显示最近的n条件命令历史:

history  #

控制命令历史的记录方式:

通过HISTCONTROL环境变量进行,其取值:

ignoredups:忽略重复的命令;重复是指连续且相同的令;

ignorespace:以空白字符开头的命令不记入历史;

ignoreboth:上述两者同时生效;

修改变量值的方式:

NAME='VALUE'

1 # echo $HISTCONTROL
2 ignoredups
3 # HISTCONTROL="ignoreboth"
4 # echo $HISTCONTROL
5 ignoreboth

c、bash特性之三:快捷键

Ctrl+a:跳至命令行首;

Ctrl+e:跳至命令行尾;

Ctrl+k:删除光标所在处至尾部的内容;

Ctrl+u:删除行首至光标所在处的内容;

d、bash的特性之四:命令补全和路径补全

命令补全:

shell程序在接收到用户执行命令的请求且分析完成之后,最左侧字符串将被当作命令去查找;

 查找机制:

(1) 查找内部命令;

(2) 查找外部命令:

1、去$PATH变量所指定的各路径下,自左而右逐个搜索各目录下的文件名;

2、给定的打头的字符串如果能惟一标识某命令程序文件的文件名,则直接补全;

3、不能惟一标识,再击tab可给列表;

4、错误:没有任何命令可被此打头字符串标识;

路径补全:

在给定的起始路径的上级目录下,以对应路径下的打头字符串来逐一匹配上级目标下的每个文件:

惟一标识:tab补全;

不能惟一标识:tab, tab给出列表;

错误路径:没有响应;

e、bash的特性之五:命令行展开:

把命令行的给定的特殊符号自动替换为相应字符串的机制;

~: 自动替换为用户家目录;

~USERNAME:自动替换为指定用户的家目录;

{}:可承载一个以逗号分隔的路径列表,能够将其展开为多个独立路径;

    例如:
           
            /tmp/{a,b,c} /tmp/a /tmp/b /tmp/c
           
            /tmp/{a,b}/z /tmp/a/z /tmp/b/z

1 # cd ~
2 # pwd
3 /root
4 # cd ~testuser
5 testuser]# pwd
6 /home/testuser

f、bash特性之六:命令的执行状态结果:

命令的正常输出结果:命令的返回值;

 通过引用来保存下来或直接调用——“命令引用”

'COMMAND'

$(COMMAND)

1 # ls -ld 'pwd'
命令的执行状态结果:

成功:0

失败:1-255

1 # echo "Helllo World"
2 Helllo World
3 # echo $?
4 0
5 # echoa "Hello World"
6 -bash: echoa: command not found
7 # echo $?
8 127
bash用一个特殊变量来保存最一次执行的命令的状态结果:

$?

bash中的引用:

'':强引用

"":弱引用

“:命令引用

1 # echo '$PATH'
2 $PATH
3 # echo "$PATH"
4 /usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin5 :/usr/bin:/root/bin
6 # echo 'pwd'
7 /home/testuser

g、bash的特性之七:glob

glob:文件名通配;快速引用多个文件;文件名整体匹配度检测;
元字符:基于元字符可编写匹配模式(pattern);

*:匹配任意长度的任意字符;

,pap,

p*:pa, p

?:匹配任意单个字符;

        p?, p?a, p??

p??: pa, pad, 

[ ]:匹配指定集合内的任意单个字符;

        [a-z], [A-Z]:不区分字符大小写;

[0-9]

    [a-z0-9]

[[:upper:]]:所有大写字母;

[[:lower:]]:所有小写字母;

        [[:digit:]]:所有的数字;

[[:alpha:]]:所有字母;

[[:alnum:]]:所有字母和数字;

[[:space:]]:空白字符;

[[:punct:]]:标点符号;

[^ ]:匹配指定集合外的任意单个字符;

[^[:alpha:]]

测试:

1、显示/etc目录下,以非字母开头,后面跟了一个字母及其它任意长度任意字符的文件或目录;
 ls -d /etc/[^[:alpha:]][a-z]*
 
2、复制/etc目录下,所以n开头,以非数字结尾的文件或目录至/tmp/etc目录下;
mkdir /tmp/etc
cp -r /etc/n*[^0-9] /tmp/etc/

3、显示/usr/share/man目录下,所有以man开头,后跟一个数字结尾的文件或目录;
ls -d /ur/share/man/man[0-9]

4、复制/etc目录下,所以p,m,r开头的,且以.conf结尾的文件或目录至/tmp/conf.d目录下;
mkdir /tmp/conf.d/
cp -r /etc/[pmr]*.conf /tmp/conf.d/

h、bash特性之八:变量

程序:指令+数据

数据:文件、变量;

变量:内存空间,有名称,名称即为变量名,对应的内存空间中的数据即为变量的值;

变量赋值:NAME=VALUE

=:赋值符号;

把VALUE存储到NAME指向的内存空间中;

编程语言:

强类型:严格区分变量中的数据类型;

弱类型:不区分变量中存储的数据类型,统一为字符型;

bash:统统默认为字符型数据;变量无需事先声明;

变量为什么有类型?

存储空间、存储格式、参与的运算、……

  类型不同决定对数据的处理方式不同

变量命名:只能使用字母、数字和下划线;而且不能以数字开头;

变量名:见名知义;不能使用程序保留字,例如if、case、then、fi、esac、for、while、until、break、continue等等;

变量引用:${NAME}, $NAME

 变量替换:把变量引用符号出现的位置替换为其指向的内存空间中的数据;

bash变量种类:

本地变量:作用域为当前shell进程;不包括其子进程;

环境变量:使用域为当前shell进程及其子进程;

局部变量

   作用域:生效范围,也即可引用到的范围;

位置参数变量:

特殊变量

本地变量:

变量赋值:NAME=VALUE

变量引用:$NAME, ${NAME}

""

查看变量:set

撤销变量:unset NAME

注意:此处非为变量引用,因此不能使用$;

所有的本地变量在shell进程终止时,会被自动撤销;

环境变量:

变量声明和赋值:

declare -x NAME[=VALUE]

export NAME[=VALUE]

引用方式:

${NAME}, $NAME

注意:bash内嵌了许多环境变量,名称为全大写字母,例如UID、HOME、PWD、SHELL, PATH, HISTSIZE等等;

环境变量查看:

export, declare -x

env, printenv

撤销环境变量:

unset NAME

只读变量:常量

(1) declare -r NAME

(2) readonly NAME

不支持重新赋值,也不支持撤销操作;

1 # declare -r username='whoami'
2 # echo $username
3 root
4 # unset username
5 -bash: unset: username: cannot unset: readonly variable

i、bash基于特性之九:I/O重定向和管道

程序的数据流有三个:

输入数据流: <–,标准输入(stdin),键盘;
输出数据流:–>,标准输出(stdout), 显示器;
错误数据流:–>,错误输出(stderr),显示器;

fd:file descriptor,文件描述符;

stdin: 0

stdout: 1

stderr: 2

IO重定向:

输出重定向:

重定向程序正常执行的结果

COMMAND > /PATH/TO/SOMEFILE

覆盖重定向:覆盖目标文件中的原有内容;

COMMAND >> /PATH/TO/SOMEFILE

追加重定向:追加新产生的内容至目标文件尾部;

shell的一个功能开关:

set -C

禁止覆盖输出重定向至已存在的文件;

注意:此时仍然可以使用“>|”至目标文件;

set +C

关闭上述特性;

错误重定向:

重定向错误的执行结果;

COMMAND 2> /PATH/TO/SOMEFILE

错误输出覆盖重定向;

COMMAND 2>> /PATH/TO/SOMEFILE

错误输出追加重定向;

合并标准输出与错误输出流:

(1) &>, &>>

(2) COMMAND > /PATH/TO/SOMEFILE 2>&1

COMMAND >> /PATH/TO/SOMEFILE 2>&1

特殊输出目标:/dev/null

位桶:bit bucket

特殊的输入文件:/dev/zero

输入重定向:

COMMAND < /PATH/FROM/SOMEFILE

tr命令:把输出的数据当中的字符,实现对位转换,即把数据中的存在于字符集中的字符,统统转换为字符集2中对应的字符;

tr – translate or delete characters

tr [OPTION]… SET1 [SET2]

(1) tr SET1 SET2 < /PATH/FROM/SOMEFILE

字符转换

1 # cat test
2 Hello World
3 # cat test |tr 'a-z' 'A-Z'
4 HELLO WORLD

(2) tr -d SET1 < /PATH/FROM/SOMEFILE

删除

1 # cat test
2 Hello World
3 # cat test |tr -d 'ldH'
4 eo Wor

COMMAND << :

Here Document

用法:

COMMAND << EOF

COMMAND > /PATH/TO/SOMEFILE << EOF

管道:

COMMAND1 | COMMAND2 | COMMAND3 | …

练习1:把/etc/passwd文件最后三行信息中所有小写字符改为大写后输出;

1 # tail -3 /etc/passwd|tr 'a-z' 'A-Z'
2 TEST1:X:5002:5002::/HOME/TEST1:/BIN/BASH
3 TEST2:X:5003:5003::/HOME/TEST2:/BIN/BASH
4 TEST3:X:5004:5004::/HOME/TEST3:/BIN/BASH

练习2:取出/etc/fstab的第6行;

1 # head -6 /etc/fstab |tail -1
2 # Accessible filesystems, by reference, are maintained under '/dev/disk'

练习3:取出/etc目录下所有以p开头的文件或目录,只显示前5个;

1 # ls -d /etc/p*|head -5
2 /etc/pam.d
3 /etc/passwd
4 /etc/passwd-
5 /etc/pinforc
6 /etc/pkcs11

tee命令:

tee – read from standard input and write to standard output and files

tee [OPTION]… [FILE]…

-a:使用追加输出,而非覆盖;

COMMAND | tee /PATH/TO/SOMEFILE

1 # cat test|tee /tmp/test.cat
2 Hello World
3 # cat /tmp/test.cat
4 Hello World

shell的展开

花括号展开

在非引号内的内容,如果用花括号包括,而且里面用逗号分隔(至少包含一个逗号,可以是空内容),这样花括号里的内容会被展开成用空格分开的一个列表,花括号前后可以紧随前缀和后缀(前后缀都是可选的)。
例如:
echo {a,b,c}
echo hello,{world,pig}
echo rep{,,,,,}eat
注意花括号展开,前缀不能是$,因为${...}在shell中是变量

波浪号展开

从波浪号~到第一个未被引号包含的斜杠/(如果没有斜杠,则全部算上),作为波浪号前缀。
在波浪号后面的字符串作为一个可能的登录名:如果为空,被展开成该用户的HOME变量,如果HOME变量未设置,则用用户执行shell的主目录替换。如果不为空,则按照该登录名的主目录替换
例如:
echo ~ # 显示$HOME内容
HOME=/bin && echo ~ # 显示/bin
unset HOME && echo ~ # 显示当前用户主目录
echo ~root # 显示root用户主目录

波浪号还可以与加减号和数字,产生一个遍历文件夹堆栈的效果(关于文件夹堆栈,参考dirs、pushd、popd几个命令)。
echo ~+ # 显示$PWD
echo ~- # 显示$OLDPWD
echo ~+2 # 显示dirs中第3个内容,索引基于0
echo ~-3 # 显示dirs中倒数第4个内容,索引基于0
如果无法展开,那就会原样显示,例如dir堆栈中只有1个内容,那么+1是无法展开的(这时只有+0有效)。

Shell参数和变量展开

用$符号开始,后面接着变量名或者花括号括起来的变量名,如果是花括号内以叹号开头,那么就是变量名本身。
例如:
echo $PWD # 显示PWD对应的值
echo ${PWD} # 显示PWD对应的值
echo ${!PWD} # 显示“PWD”这个变量名,而不是它的值
echo ${!P*} # 显示所有以P开头的环境变量名
如果一个变量名不存在,就创建它。
echo ${HELLO:=hello} # 如果HELLO不存在,就用hello给它赋值,否则直接输出$HELLO的值

算术展开

放在$(( ))中的表达式会被计算,其中变量会被求值,例如:
a=1 && b=3 && echo $(($a+$b))
如果是数字,0开头的8进制,0x开头的16进制,其它进制用Base#number的方式
可支持2~64进制,如果进制小于等于36,可以用a-z或A-Z表示10-35,如果进制大于36,则a-z表示10-35,A-Z表示36-61,@表示62,表示63
例如:
echo $((16#32)) # 16进制的32,输出50
echo $((64#@
)) # 输出4031 = 62 * 64 + 63
用$[]也可以算术展开,但是不要和测试条件[]混淆了
例如:
echo $[1+4]

文件名展开

进行字词分隔后,如果不指定-f选项,shell会搜索"*","?","[",如果遇到了,就会认为是一个带pattern的word,然后用字典序将符合的所有文件名替换过去,如果没有文件名匹配:1 shell的nullglob选项关闭,则不进行文件名展开,保留word原样;2 shell的nullglob打开,则移除这个word。如果shell的nocaseglob选项打开,则忽略大小写。

当匹配文件名时(这里指不包括文件夹),除非shell的dotglob被设置,否则.或./开头的文件都必须显示指定,例如:
ls * # 列出当前文件夹中所有不以"."开头的文件
ls .* # 列出当前文件夹中所有以"."开头的文件
当匹配文件名时,"/"必需显示匹配,例如:
ls ./* 和 ls .//是不同的。
其它情况下,"."和普通字符一样,例如:
.txt和txt都可以匹配a.txt

还有一个系统变量GLOBIGNORE,如果一个文件名匹配了一个pattern word,但是它也匹配了GLOBIGNORE,则它会被忽略,不过两个特殊文件一定会被忽略,就是"."和".."。
如果GLOBIGNORE打开,那么dotglob选项也会自动打开,这样会导致当你ls 时,其他以"."开头的文件也会被match,如果想忽略"."开头的文件,可以在GLOBIGNORE里面添加一个"."的匹配。如果GLOBIGNORE未设定,则dotglob关闭。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容