实用 Shell 文档

Shell 文档

ChinaUnix上大神網中人总结的Shell十三问?强烈推荐,这本书讲得比较精炼,而且都是一些Shell学习中容易把握不住的一些细节难点。每一问都写得非常精彩。

同样是ChinaUnix上,wingger大神整理的Shell基础二十篇。这份文档涉及的内容比较多,我没记错的话应该有很多命令的用法,而且配备实际使用的例子,对初学者帮助甚大。

Shell脚本专家指南也是一本不可多得的好书,我是之前在学校的时候买的这本书。上面都是作者实际工作中的经验总结,你可以从中学到很多其它书上学不到的实践知识。千万不要被专家两个字吓住了,书名的意思是专家给你总结的学习指南。

注:mingxinglai也在他的博客文章shell脚本学习材料种整理了很多实用的资料。

正则表达式

我个人学习正则表达式是从正则表达式30分钟入门教程开始的,这份文档让我了解了正则表达式的一些基础术语和基本的用法。

继续阅读

简洁的 Bash Programming 技巧续篇

简洁的 Bash Programming 技巧系列文章专门介绍Bash编程中一些简洁的技巧,帮助大家提高平时 Bash 编程的效率。继上一篇文章发布后,收到很多读者的反响,所以我决定继续将自己学到的一些新的技巧更新在这篇续篇中,当然也希望其它同学也能一起分享你们的技巧。续篇中有部分的内容已经偏离bash编程了,而是命令行下的技巧,题目我暂时不改,请见谅。

1. bash中alias的使用

alias其实是给常用的命令定一个别名,比如很多人会定义一下的一个别名:

alias ll='ls -l'

以后就可以使用ll,实际展开后执行的是ls -l。现在很多发行版都会带几个默认的别名,比如:

alias grep='grep --color=auto'  # 带颜色显示
alias ls='ls --color=auto' # 同上
alias rm='rm -i'  # 删除文件需要确认

alias在某些方面确实提高了很大的效率,但是也是有隐患的,这点可以看我以前的一篇文章终端下肉眼看不见的东西。那么如何不要展开alias,而是用本来的意思呢?答案是使用转义:

\ls
\grep

在命令前面加一个反斜杠后就可以了。

继续阅读

简洁的 Bash Programming 技巧

简洁的 Bash Programming 技巧这一系列文章专门介绍Bash编程中一些简洁的技巧,帮助大家提供 Bash 编程的效率,目前该系列已经有三篇文章,有兴趣的同学可以继续阅读其它两篇续篇(一)(二)

下面这几条是我自己在写shell代码的时候,比较喜欢的几种写法,抛砖引玉。

1. 检查命令执行是否成功

第一种写法,比较常见:

echo abcdee | grep -q abcd

if [ $? -eq 0 ]; then
    echo "Found"
else
    echo "Not found"
fi

简洁的写法:

if echo abcdee | grep -q abc; then
    echo "Found"
else
    echo "Not found"
fi

当然你也可以不要if/else,不过这样可读性比较差:

[Sun Nov 04 05:58 AM] [kodango@devops] ~/workspace 
$ echo abcdee | grep -q abc && echo "Found" || echo "Not found"
Found

2. 将标准输出与标准错误输出重定向到/dev/null

第一种写法,比较常见:

grep "abc" test.txt 1>/dev/null 2>&1

常见的错误写法:

grep "abc" test.txt 2>&1 1>/dev/null

继续阅读

Bash 获取当前函数名

在C/C++中,__FUNCTION__常量记录当前函数的名称。有时候,在日志输出的时候包含这些信息是非常有用的。而在Bash中,同样有这样一个常量FUNCNAME,但是有一点区别是,它是一个数组而非字符串,其中数组的第一个元素为当前函数的名称。

可能初看有点难以理解,为什么FUNCNAME要是一个数组呢?看看下面的例子,你就明白了。

#!/bin/bash

function test_func()
{
    echo "Current $FUNCNAME, \$FUNCNAME => (${FUNCNAME[@]})"
    another_func
    echo "Current $FUNCNAME, \$FUNCNAME => (${FUNCNAME[@]})"
}

function another_func()
{
    echo "Current $FUNCNAME, \$FUNCNAME => (${FUNCNAME[@]})"
}

echo "Out of function, \$FUNCNAME => (${FUNCNAME[@]})"
test_func
echo "Out of function, \$FUNCNAME => (${FUNCNAME[@]})"

执行后的结果为:

Out of function, $FUNCNAME => ()
Current test_func, $FUNCNAME => (test_func main)
Current another_func, $FUNCNAME => (another_func test_func main)
Current test_func, $FUNCNAME => (test_func main)
Out of function, $FUNCNAME => ()

继续阅读

终端下肉眼看不见的东西

假设test目录下面有a.log、b.log和c.log三个文件:

# ls -1 *.log
a.log
b.log
c.log

现在,我们想要遍历这几个文件,找到关心的信息,例如log文件中是否存在error信息。那么,我们会考虑写一个for循环来处理这个问题:

# for i in `ls -1 *.log | sed '$d'`; do
> grep 'err' $i
> done

非常简单的一个循环,但是执行后会发现以下错误:

grep: a.log: No such file or directory
grep: b.log: No such file or directory
grep: c.log: No such file or directory

非常奇怪,不是*.log这几个文件都在当前目录存在着的吗?为什么这里又找不到呢?
继续阅读

什么是交互式登录 Shell

今天在看~/.bashrc文件的时候看到一行,对它的意思不是非常了解:

[[ $- != *i* ]] && return

就特意上Google搜索了一下,对于搜索关键字是符号(这里是$-)的,我是不怎么抱希望的。所以干脆将$-的结果(himBh)放到Google一起搜索。果然找到两篇不错的帖子:

这两个帖子都是在ChinaUnix论坛上的。这些老论坛虽然人气不行,但是一些资源还是很赞的,这些总结帖都非常好。尤其是第一篇非常值得一读,我只是看了其中一部分。对sh和bash的区别并没有仔细看,觉得这些没必要去死记,到时候碰到问题再去理解就好,要不然就太枯燥了。

Linux用了这么多年,Shell一直在用,执行命令,安装软件,配置文件,以及编写脚本,但是说真地,我对Shell一直不是非常了解,几乎没看过和它相关的任务手册和文档。一般系统中最常见的Shell还是Bash。Bash的手册非常长,我是坚决不看的,头痛。后果就是对Bash的一些现象一知半解,其实这些基本上在手册上都是有写的。

继续阅读