Learning Bash

学习Bash,记录一些新学到的知识和tips。

Tips 1 &&||

&&||在条件判断时分别表示“逻辑与”和“逻辑或”,等同于在c中的功能。

另外,它们还可以直接用于命令后面,如:

command1 && command2 ||command3

上面的意思为:如果命令command1正常完成(返回0),则执行command2 如果command2执行时发生错误(返回非0),则执行command3

如果commandn执行多条语句,可以写为command1; command2; ......,如果代码为下面的形式:

command1; command2 && command3; command4 || command5; command6

如果期待command2正常完成后执行command3command4,出错时执行命令command5command6。那就错了。上面的写法中,命令 command1, command2, command4, command6一定会被执行, command3command5则依情况而定。如果期待如前所述,则必须将 command3; command4command5; command6用”`“括起来,如:

command1; command2 && `command3; command4` || `command5; command6`

Tips 2 关于删除文件时使用引号的疑问

假定目录结构如下:


tree abc
.
├── a
└── b
└── c

2 directories, 1 file

目标是将目录abc清空。看看下面两个命令,你认为它们的效果是一样么?

rm -rf "abc/*"
rm -rf abc/*

动手试试上面两个命令,看看结果如何?第一个命令rm -rf "abc/\*"不能删除目录abc下的内容,而第二个命令可以。原因是什么?

Tips 3 防御型代码

今天看《Shell脚本学习指南》p307页时,发现一段代码:

grep POSTX_OPEN_MAX /dev/null $(find /usr/include -type f | sort)

就觉得奇怪,为什么要加一个/dev/nullgrep后面。

因为如果$(find /usr/include -type f | sort)返回为空,grep命令就会一直等待终端输入,导致程序“卡死”。 添加一个/dev/null的作用就是防止find返回为空是程序卡死发生

Tips 4 终端打印彩色文字

使用Shell在终端打印彩色文字:

echo -e "\e[32mHello World!\e[0m"

Python的print语句也可以利用相似的语法在终端打开彩色文字:

print("\x1B[32mHello World\x1B[0m")

# Python彩色文字
green = lambda string: '\x1B[32m%s\x1B[0m' % string
yellow = lambda string: '\x1B[31m\x1B[1m%s\x1B[0m' % string
red = lambda string: '\x1B[33m\x1B[1m%s\x1B[0m' % string

warning = lambda msg: '[%s]: %s' % (yellow('警告'), msg)
error = lambda msg: '[%s]: %s' % (yellow('错误'), msg)

Note

Below are the color init strings for the basic file types. A color init string consists of one or more of the following numeric codes:

Attribute codes:
00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
Text color codes:
30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
Background color codes:
40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white

Tips 5 求N天前的日期字符串

个人觉得这个问题要完全正确是要花一点力气的,首先必须考虑以下情况:

  • 每个月天数不一样,有28, 30, 31
  • 存在闫年情况,二月份有29天

所以用Shell内置的功能偷了一下懒[1]

#!/bin/bash

# Author: Liu Hui
# 
# Date: Thu Jul  4 23:42:53 CST 2013


SECOND_TODAY=`date +%s`
SECOND_PER_DAY=86400

INTERVAL=7

SEQ=`seq $INTERVAL`

#set -x
for i in $SEQ
do
    DATE=`echo "$SECOND_TODAY - $SECOND_PER_DAY * ${i}" | bc`
    echo `date --date="@$DATE" +%Y%m%d`
done
#set +x
  • 利用date命令自身功能更加简单方便:
date -d '-2 day' '+%Y%m%d'
# output:   20140118