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


用<()以上可以用oneline单行来代替:
diff <(grep keys file1)<(grep keys file2)
引用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 。
:h
如果把该操作符放在一个文件名后面,它会删除文件夹以外的文件名称 。比如:
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 [ $(grep XXX /dev/null) = '' ]
then
echo -n Chongchong
else
echo -n lo
fi
if [[ $(grep XXX /dev/null) = '' ]]
then
echo -n Chongchong
else
echo -n lo
fi
[是测试的原始形式,然后[[引入了更灵活和直观的方式 。在上面的第一个if块中,if语句因为$(grep XXX /dev/null)被评估为空,导致这种比较:[=''],这会抛出错误,针对这种情况就需要使用[[]]来避免这种异常,还有一个常用的技巧是使用:
if [x$(grep XXX /dev/null)='x']
所以,如果命令没有返回任何内容,它仍然可以正常运行,而不会抛出异常,中断执行 。
退出状态码我们知道每次shell执行,推出是都会给shell一个状态码 。
如果命令执行正常,则会返回给shell状态码0 。如果不成功,则会得到一个非零代码,用来表具体错误的种类,其中 1表示"一般错误",还有其他更多信息,可以在程序中具体定义 。状态码,可以通过$?查看 。但有些命令会设置有特殊设置比如grep,请尝试下面的命令:
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 。


推荐阅读