Linux命令行基础, 关于Bash需要知道的一些常识
栏目:行业动态 发布时间:2019-08-15 19:26
Linux命令行基础, 关于Bash需要知道的一些常识

引导顺序

首先我们要说下bash脚本的启动,Linux中初始化都是按照一定顺序加载各个文件初始化脚本脚本所在文件启动顺序很重要,下面这个图显示了Linux个初始化脚本和环境变量的加载顺序,包括了bash、sh和zsh等常见的shell。

Linux命令行基础, 关于Bash需要知道的一些常识

bash的加载遵循上图,从上到下顺序执行加载,尤其要注意non-login非交互执行,它不会加载很多脚本,比如/etc/profile/etc/bash.bashrc和个人的.profile, .bash_profie,.bash_login和.bashrc等。所以如果你脚本处于这样环境下你就要在脚本中自我设置一些环境变量。这样就可以避免由于环境变量导致的一些莫名其妙的问题,比如写的好脚本为什么登陆就可以执行,放到cron里面自动执行为什么就不行。

输入/输出和重定向

我们知道Linux下一切皆文件,包括硬件设备,其中三个特殊的文件句斌,标准输入标准输出和标准错误其句柄号为三个整数0,1和2。

:用于重定向改变标准输出

1> :1> 和>一样 ,> 默认的FD为1。

2> :改变标准错误

>> :重定向输出到文件,追加到文件末尾。

set -o noclobber :设置 > 不能覆盖已经存在的文件。

set +o noclobber :这支 > 可以覆盖已经存在的文件。

> :设置set -o noclobber后,使用 > 可以临时覆盖已经存在的文件。

/dev/null 和 /dev/zero

command > /dev/null

可以将stdout、stderr都重定向输出到/dev/null:

command > /dev/null 2>&1 或者

command &> /dev/null

command >& /dev/null

/dev/zero 设备用于提供无限制的空null内供读取。当读取该设备时候,它会提供无限的空字符 null。我们可以从/dev/zero 读取任意数量的 null 字符。和 /dev/null 不同,/dev/zero主要用于作为null数据源供读取,当然/dev/zero也支持写入,可以用做数据黑洞。

/dev/zero主要用途是提供字符流来初始化数据存储,也就是使用空字符覆盖目标数据。还可以用来一个特定大小的空白文件。

比如用空白文件覆盖分区,删除分区的数据可以用慎用!:

dd if=/dev/zero of=/dev/

创建一个一个1M的文件,可以使用

``和$

反引号和$,两者基本上类似,在shell中都表示执行命令。

echo`ls`

echo $

最常用的用法是将一些命令结果输出传递个其他命令作为参数。比如要查询当前目录和子目录下所有PHP中的包含“eval”函数可以用下面命令:

grep eval `find -type f -name “*.php”`

两者主要的区别在于嵌套更简单。

对``来说要实现嵌套就要增加很多反斜杠来转义,比如:

echo `echo `echo `echo hello,Chongchong!```

而用$就简介的多了:

echo $

这是个很有意义的操作符,他有点类似于$,而可以括弧中命令的输出重用。但是在

比如我们要执行下面一些例子

grep keys file1> /tmp/a

grep keys file2> /tmp/b

diff /tmp/a /tmp/b

diff

引用

bash引用就比较复杂内容很多,我们先从简单的开始。

首先,引号中的变量:

A=“123”

echo “$A”

echo “$A”

这个结果很简单,双引号会解释变量,输出为其值123,而单引号不会解释,输出为$A。

下面三个echo 都会打印啥呢?

mkdir -p tmp

cd tmp

touch a

echo *

echo “*”

echo “*”

Bash中有很多引用方式的快捷方式,其中一些可以极大的提高我们的工作效率

表示重复最后一个命令的最后一个参数。如果你正在处理一个文件,通过该操作符可以在命令后重新引入参数,从而节省大量重复输入。

grep xxx /long/path/to/some/file/or/other.txt

vim !$

1-$

该操作符,更有意思,它获取上一个命令的所有参数并将它们引入。所以:

grep isthere /long/path/to/some/file/or/other.txt

egrep !1-$

fgrep !1-$

表示“查看上一个命令”:是一个分隔符,1表示“取第一个单词” -表示范围“直到”$表示“最后一个单词”

我们可以用!*实现同样的目的。但是基于上述规则,我们就可以随意定制参数的范围了。比如如使用!2-3。

如果把该操作符放在一个文件名后面,它会删除文件夹以外的文件名称。比如:

grep XXX /long/path/to/some/file/or/other.txt

cd !$:h

通配符和正则表达式

通配符和正则表达式中都会用*,看起来很相似,但它们差异很大

请解释下面这个命令:

rename -n “s//HEAD$1/” *

上面两个星号表达意思完全不同:

第一个由于用单引号括住,shell不会对其解释,作为参数都提交给rename命令。rename会对其解释 ,而s//HEAD$1/是一个正则替换。在正则表达式中 *表示对前面字符的0个或者多个模式。.表示一个字符,所以.*表示匹配所有内容;表示对括住内容进行应用,在替换后面用1或者$1表示它。

第二个会被shell解释,*在shell中表示通配符,表示当前工作文件夹中所有文件的列表替换。

所以整个命令表示将文件下所有文件名都增加上HEAD 前缀。请尝试下面两个命令:

ls *

ls .*

第二个看起来更像是一个正则表达式,但是实际是什么样的呢?请你解释下。

条件语句,和

请尝试执行一下语句会输出什么?

if grep XXX /dev/null

then

echo Chongchong

else

echo lo

fi

grep的返回代码使得像这样的代码更直观地作为其使用退出代码的副作用。

下面两个语句的输出呢?

if

then

echo -n Chongchong

else

echo -n lo

fi

if

then

echo -n Chongchong

else

echo -n lo

fi

是的原始形式,引入更灵活和直观的表示方式。在上面的第一个if块中,if语句因为$被评估为空,导致这种比较:=,这会抛出错误,针对这种情况就需要来避免这种异常,还有一个常用的技巧是使用:

if x$=“x”

所以,如果命令没有返回任何内容,它仍然可以正常运行,而不会抛出异常,中断执行。

退出状态码

我们知道每次shell执行,退出时都会给shell一个状态码。

grep XXX /dev/null

echo $?

Grep中使用退出代码来指示它是否匹配。

set 语句

Bash中也提供了可配置的选项,可以即时设置环境变量等。

set -e

如果任何命令返回非零退出状态,则从脚本退出。

set -X

会输出在运行时运行的命令。

所以脚本可能会使用这样的开头:

!/bin/bash

set -e

set -x

grep XXX /dev/null

echo $?

getopts

如果要写一个较大的程序,涉及的输入比较复杂使getopts来简化你的工作,用它来帮你做输入和参数处理的事情,比如下面一个例子:

Linux命令行基础, 关于Bash需要知道的一些常识

getopts后面跟的是参数列表字符串,每个字母表示一个选项,带:选项表示选项还会有值,比如上面例子中对应的-j /home/soft/java 和-m /home/soft/maven 。而getopts字符串中没有跟随:的字母就是开关型选项,不需要指定值,等同于true/false,只要带上了这个参数就是true。

getopts是shell内部命令,可以在shell脚本中直接使用,同时shell也支持一个外部命令getopt很多发行版本也都再带详细可以搜索或者参考具体文档,本文不在赘述。

总结:

本文相关词条概念解析:

文件

文件是现代词,是一个专有名词,指的是形成的正式文书,分为公文、文书、函件和其他文件。狭义的“文件”就是档案的意思,广义的“文件”指公文书信或指有关政策、理论等方面的文章。文件的范畴很广泛,电脑上运行的程序、杀毒等等都叫文件。

服务热线