实用bash命令记录

本篇文章记录工作中比较实用,能减轻工作量的bash命令。

1.字符串截取

假设有这么一个变量silo=/home/liujiacai/codes/cascalog/silo,那么

${silo##/*/}=silo
${silo#/*/}=liujiacai/codes/cascalog/silo

##表示取后面字符串最长的那段;#表示取最短的那段,这两个是从前面删除的

${silo%%/*/}=/home/liujiacai/codes/cascalog/silo
${silo%%/*}=       (空)
${silo%/*}=/home/liujiacai/codes/cascalog

%%和##功能相同,不过这个是从后面开始删的。第一个什么也没删除是因为silo最后一个字符为‘o’不是‘/’,所以不变

 Bash Shell可以进行变量的条件替换,既只有某种条件发生时才进行替换

 ${FOO:-word}  

当没有FOO变量时,返回word

${FOO:=word}

当没有FOO变量时,返回word,并且把word赋值给FOO变量

 ${FOO:+word}  

当定义了FOO变量时,返回word

${FOO:?msg}

当没有FOO变量时,把msg送到标准错误输出

${FOO:offset:length} 

length可以为空

${#FOO}

变量FOO字符个数

 ${FOO/pattern/string}

字符串替换,最短原则

 ${FOO//pattern/string}

字符串替换,最长原则

如果FOO=aabbbbbbbcc,那么

echo ${FOO//bb/dd}返回aaddddddbcc

echo ${FOO//bb/dd}返回aaddbbbbbcc

2.正则表达式

以前在做java开发时也无数次遇到RE(regex expression),每次看我都以为我懂了,直到今天我才算是明白,我掌握的知识永远是那么冰山一角。扯蛋完毕。

Warning:正则表达式和通配符(wildcard)不一样。

正则表达式分基本RE与扩展RE之分,Bash中有个命令默认只认识基本的,比如grep,但是通过-e参数就能识别扩展的了;有的可以认识扩展,这点一定要搞清楚。

在基本表达式中有这么几个特殊字符,一定要记住

基本正则表达式的特殊字符
RE字符 含义与范例
^word 待搜索的字符串(word)必须在行首
word$ 待搜索的字符串(word)必须在行尾
. 代表任意一个字符
\ 转移符,将有特殊符号的特殊意义去掉
* 重复前一个字符,一次或多次。WARN:这里和通配符中*含义不同
\{n,m\} 连续n到m个的“前一个重复字符”
[word] []内的字符集合中任取一个字符 h[io]t  代表的是hit或者hot;其次是[0-9]、[a-z]等这种用法; 再其次是[^word],表示不含“w”、“o”、“r”、“d”中的字符

再说说扩展RE的特殊字符

扩展正则表达式的特殊字符
RE字符 含义与范例
+ 重复前一个字符一次或一次以上,比如go+d,,可以表示god、good、goood等等
重复前一个字符零次或一次,比如go?d,表示gd、god
| 表示或的意思,比如'gd|good',表示取gd或者good
() 分组处理字符,比如'g(la|oo)d',可以表示glad或者good

再提醒一次,“!”叹号在正则表达式中并不是特殊字符。

Unix-like系统还存在一类字符串匹配机制--globbing,在globbing中,*和通配符的用法是一样的,代表零个或多个任意字符。git的.gitignore文件就是使用的这种字符串匹配模式

详情参见:http://en.wikipedia.org/wiki/Glob_(programming)

3.find命令

find path [-name] pattern  在path路径下查找名字为pattern的文件,返回基于path的相对路径

find . -type f -exec file '{}' \;
这条命令查找当前目录下的文件,并且作为file命令的参数执行。{}表示当前文件名,用单引号是防止{}被shell解释器解释为shell script punctuation,分号用反斜线也是这样目的,也可以用单引号代替反斜线。
find $HOME -mtime 0
查找$HOME文件夹下在24小时之内修改过的文件。这里用0是因为-mtime选项对于每个文件的修改时间取其除以24后的商,余数舍弃。

find repo/ -exec test -d {}/.svn -o -d {}/.git -o -d {}/CVS ; \
-print -prune
这个命令是用来查看项目的是否有.svn与.git与CVS目录的,-o 是-or的简写,表示前面的命令为false时才执行,{}表示当前处理的文件夹名,-prun e选项可以防止不必要的嵌套查找,假设repo有如下目录结构:

repo/project1/CVS
repo/gnu/project2/.svn
repo/gnu/project3/.svn
repo/gnu/project3/src/.svn
repo/project4/.git

带上-prune选项后就不会再搜索project3/.src目录了,因为已经找到了project3/.svn了。

4.xargs

这个命令在管道中特别有用

  find /tmp -name core -type f -print | xargs /bin/rm -f 
这条命令查找/tmp文件夹下名为core的文件,并且把它删除。这时的文件名中不能有空格、换行符,解决方法是加上 -0参数。

当然上面这条命令还可以这么写:

 find /tmp -depth -name core -type f -delete
 
利用find的参数-delete选项,这样比用xargs效率更高,因为这样不用再调用 fork(2) and exec(2) 来launch rm和xargs进程。

这里的-depth选项指明“先处理文件夹中的内容在处理文件夹本身”,-delete本身就暗含了-depth选项。

<span style="font-family:System;">cut -d: -f1 < /etc/passwd | sort | xargs</span>
这条命令用于显示passwd文件中记录的当前系统的用户。

需要注意的时,xargs并不能一定保证,命令正确执行,有可能xargs后面的命令在接受管道前面的输入时,系统执行其他命令,改变了xargs的输入。


5. bash中的比较

bash中有个test命令可以进行一系列的测试,man 一下可以看到解释为" check file types and compare values",具体语法为

test EXPRESSION
其实我们最常用的是test的一个别名"[",没错,就是左方括号,语法为

[ EXPRESSION ]

EXPRESSION后面的右方括号是作为结束只用,没什么实际含义.

如果忽略EXPRESSION,那么返回false. 常用的EXPRESSION有如下这么几个:

( EXPRESSION )
      EXPRESSION is true  需要注意一点的是,括号"(",")"需要用"\"转义
! EXPRESSION
      EXPRESSION is false
EXPRESSION1 -a EXPRESSION2
      both EXPRESSION1 and EXPRESSION2 are true
EXPRESSION1 -o EXPRESSION2
      either EXPRESSION1 or EXPRESSION2 is true
-n STRING
      the length of STRING is nonzero.STRING equivalent to -n STRING
-z STRING
      the length of STRING is zero
STRING1 = STRING2
      the strings are equal
STRING1 != STRING2
      the strings are not equal
INTEGER1 -eq INTEGER2
      INTEGER1 is equal to INTEGER2
INTEGER1 -ge INTEGER2
      INTEGER1 is greater than or equal to INTEGER2
INTEGER1 -gt INTEGER2
      INTEGER1 is greater than INTEGER2
INTEGER1 -le INTEGER2
      INTEGER1 is less than or equal to INTEGER2
INTEGER1 -lt INTEGER2
      INTEGER1 is less than INTEGER2
INTEGER1 -ne INTEGER2
      INTEGER1 is not equal to INTEGER2
FILE1 -ef FILE2
      FILE1 and FILE2 have the same device and inode numbers
FILE1 -nt FILE2
      FILE1 is newer (modification date) than FILE2
FILE1 -ot FILE2
      FILE1 is older than FILE2
-d FILE
      FILE exists and is a directory
-e FILE
      FILE exists

test的这些Express和我们平常用的C/Java语言系列的判断不一样(比如需要对一些字符进行转义),这点让我们很不是适应,不过幸好,bash提供了补救方案,那就是"[[",使用"[["可以对文件名和字符串使用更自然的语法。可以用括号和逻辑操作符把 test 命令支持的测试组合起来。下面给出一个示例:

使用 [[ 复合命令,这里不再需要对"("与")"进行转义

[[ ( -d "$HOME" ) && ( -w "$HOME" ) ]] &&  echo "home is a writable directory"

参考:

http://www.ibm.com/developerworks/cn/linux/l-bash-test.html




你可能感兴趣的:(linux,bash)