脚本编程 类目

脚本语言(英语:Scripting language)是为了缩短传统的“编写、编译、链接、运行”(edit-compile-link-run)过程而创建的计算机编程语言。脚本语言是运维工程师的一大利器,常用的脚本语言有 Python、Shell、Perl 等。

Bash One-Liners Explained 译文(一)

Bash One-Liners Explained 是一系列介绍 Bash 命令技巧的文章,由国外牛人 Peteris Krumins 撰写。凭借扎实的功底和丰富的经验,作者总结了许多快速解决问题的技巧,并且每一条都只要用简洁的一行 Bash 命令就可以完成,同时每一行命令文中都给出了非常详尽的解释。

Peteris Krumins 是一位高产的博主,在他的博客上有很多非常精彩的文章,推荐大家有机会都可以去好好读一读。例如,大家耳熟能详的 Awk One-Liners ExplainedSed One-Liners Explained 等等。后者我也北曾经在博客上分享过一篇笔记

回到正题,虽然这一系列文章不难,但是还是可以从中学到很多细节的知识,相信这些肯定会对许多初学者有所帮助,所以我打算将这一系列翻译成中文,分享给大家。为了同原文保持一致,这一系列文章最终会分成以下五篇:

  1. Bash One-Liners Explained 译文(一): 文件处理
  2. Bash One-Liners Explained 译文(二): 操作字符串
  3. Bash One-Liners Explained 译文(三): 漫谈重定向
  4. Bash One-Liners Explained 译文(四): 历史命令
  5. Bash One-Liners Explained 译文(五): 命令行跳转

本系列的文章同其它系列一样,最终都可以在连载页面找到,有兴趣的同学可以随意翻翻,看看有没有一些对你有价值的文章,大家一起交流学习。

1. 清空文件内容

$ > file

这一行命令用到了输出重定向操作符>。输出重定向发生时,文件会被打开准备写入。如果此时文件不存在则先创建,存在则将其大小截取为0。这里我们并没有重定向写任何内容到文件中,所以文件依然保持为空。

如果你想替换文件的内容,或者创建一个包含指定内容的文件,可以运行下面的命令:

$ echo "some string" > file

2. 追加内容到文件

$ echo "foo bar baz" >> file

查看全文

Shell 默认选项 himBH 的解释

SegmentFault 的问题地址: 求大大解释如下shell语句

$ echo $-
himBH

1、himBH这个结果又是什么意思?
2、看不懂,求第69行详解。多谢++

for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done

以下是我的回答:

1. himBH 这个结果又是什么意思?

$-记录着当前设置的shell选项,himBH是默认值,你可以通过 set 命令来设置或者取消一个选项配置。例如:

set -x

这个可以打开 shell 的调试开关,调试 shell 脚本非常有用,这个时候再检查下 $- 变量的值,可以看到多了 x 字符:

[kodango@mac] ~ 
$ echo $-
+ echo himxBH   # -x 选项设置的效果
himxBH

回到 himBH 上,我们来一个一个看这几个默认选项分别影响了 Shell 的哪些行为。

i - interactive

包含这个选项说明当前的 shell 是一个交互式的 shell,何为交互式?你输入命令,shell 解释执行后给你返回结果,我们在 Terminal 下使用的 shell 就是交互式的,所以 $- 会包含 i 字符。如果我们在一个脚本里面 echo $-,结果是不会包含 i 的。关于交互式 Shell,我之前在博客里写过一篇文章专门介绍,有兴趣的可以看看。

H - history expand

history expand 这个很多人都基本上不用,包括我也是。我们知道 Shell 会把我们执行的命令记录下来,可以通过 history 命令查看,每一行是序号 + 执行的命令。在 shell 退出时,会将这些信息保存到~/.bash_history 文件中,当然在启动时也会从该文件中加载,不信删除这个文件再打开一个终端试试。

查看全文

mark-directory: 快速目录切换工具

今天早上看到@程序员的那些事转的一条微博《使用命令行快速操控文件系统》,文中作者介绍了他提升工作效率的一个命令行小工具,可以快速切换工作目录,我觉得蛮有意思的,小小研究了下。在原工具的基础上,我在 Github fork了一个改进的版本 —— mark-directory,具体可以看文章最后。

工作原理

这个小工具的工作原理非常简单,相信大家扫过一遍原文就可以明白,它创建了一个隐藏目录(例如~/.marks),目录里面存放的文件都是常用目录的软链接。我们可以将这个软链接看作一个书签,通过访问这个书签我们可以方便地跳转到相应的目录。

具体实现

这个小工具也提供了相应的命令来管理这些软链接文件,当前支持的是jump, mark, unmark和marks。

以上4个操作命令的实现代码如下所示,非常简单:

export MARKPATH=$HOME/.marks
function jump { 
    cd -P "$MARKPATH/$1" 2>/dev/null || echo "No such mark: $1"
}
function mark { 
    mkdir -p "$MARKPATH"; ln -s "$(pwd)" "$MARKPATH/$1"
}
function unmark { 
    rm -i "$MARKPATH/$1"
}
function marks {
    ls -l "$MARKPATH" | sed 's/  / /g' | cut -d' ' -f9- | sed 's/ -/\t-/g' && echo
}

将这段代码放到~/.bashrc 文件中。接下来我们来尝试使用这个小工具。

查看全文

Bash Pitfalls: 编程易犯的错误(四)

上一篇文章参见Bash Pitfalls: 编程易犯的错误(三)。这一篇翻译得不是非常满意,时间比较赶,请见谅,如果有问题可以在本文后方留言,大家一起深入探讨。

36. [ -n $foo ] or [ -z $foo ]

这个例子中,$foo 没有用引号引起来,当$foo包含空格或者$foo为空时都会出问题:

$ foo="some word" && [ -n $foo ] && echo yes
-bash: [: some: binary operator expected

$ foo="" && [ -n $foo ] && echo yes
yes

正确的写法是:

[ -n "$foo" ]
[ -z "$foo" ]
[ -n "$(some command with a "$file" in it)" ]

[[ -n $foo ]]
[[ -z $foo ]]

37. [[ -e "$broken_symlink" ]] returns 1 even though $broken_symlink exists

这里-e 选项是看文件是否存在,当紧跟的文件是一个软链接时,它不看软链接是否存在,而是看实际指向的文件是否存在。所以当软链接损坏时,即实际指向的文件被删除后,-e 的结果返回1。

查看全文

Bash Pitfalls: 编程易犯的错误(三)

上一篇文章参见Bash Pitfalls: 编程易犯的错误(二)

24. for arg in $*

和大多数 Shell 一样,Bash 支持依次读取单个命令行参数的语法。不过这并是$*或者$@,这两种写法都不正确,它们只能得到完整的参数列表,并非单独的一个个参数。

正确的语法是(没错要加上引号):

for arg in "$@"

# 或者更简单的写法
for arg

在脚本中遍历所有参数是一个再普遍不过的需求,所以 for arg 默认等价于 for arg in "$@"。$@使用双引号后就有特殊的魔力,每个参数展开后成为一个独立的单词。("$@"等价于"$1" "$2" "$3" ...)

下面是一个错误的例子:

for x in $*; do
   echo "parameter: '$x'"
done

执行的结果为:

$ ./myscript 'arg 1' arg2 arg3
parameter: 'arg'
parameter: '1'
parameter: 'arg2'
parameter: 'arg3'

正确的写法:

for x in "$@"; do
   echo "parameter: '$x'"
done

执行的结果为:

$ ./myscript 'arg 1' arg2 arg3
parameter: 'arg 1'
parameter: 'arg2'
parameter: 'arg3'

查看全文

Bash Pitfalls: 编程易犯的错误(二)

上一篇文章参见Bash Pitfalls: 编程易犯的错误(一)

13. cat file | sed s/foo/bar/ > file

你不应该在一个管道中,从一个文件读的同时,再往相同的文件里面写,这样的后果是未知的。

你可以为此创建一个临时文件,这种做法比较安全可靠:

# sed 's/foo/bar/g' file > tmpfile && mv tmpfile file

或者,如果你用得是 GNU Sed 4.x 以上的版本,可以使用-i 选项即时修改文件的内容:

# sed -i 's/foo/bar/g' file

14. echo $foo

这种看似无害的命令往往会给初学者千万极大的困扰,他们会怀疑是不是因为 $foo 变量的值是错误的。事实却是因为,$foo 变量在这里没有使用双引号,所以在解析的时候会进行单词拆分文件名展开,最终导致执行结果与预期大相径庭:

msg="Please enter a file name of the form *.zip"
echo $msg

这里整句话会被拆分成单词,然后其中的通配符会被展开,例如*.zip。当你的用户看到如下的结果时,他们会怎样想:

Please enter a file name of the form freenfss.zip lw35nfss.zip

查看全文

Backup Mediawiki 站点

去年,我使用 Mediawiki 搭建了一个 wiki 站点,用于团队知识积累。短短半年,已经有不少的沉淀,随着 wiki 越来越重要,它的数据安全性也必须考虑起来,因此我们准备把 wiki 迁移到 VM 上,并且考虑做好备份。迁移之前,数据备份的操作是件体力活,不过好在网上有不少的文章介绍如何操作, Mediawiki 官方也有专门的文章来介绍具体的操作过程以及需要注意的地方,详见Backing up a wiki

文章的最后还引用了一系列的备份脚本,这是我等懒人最喜欢的方法,越简单粗暴越好。看了其中的一个脚本(Backing up a wiki/Duesentrieb's backup script - MediaWiki),脚本的内容很简单,不过要想 run 起来,首先还得改动开头的几处配置,比较麻烦。

所以我自己 fork 了一个新的版本,通过命令行参数的形式提供配置,并且修复了脚本的几处 Bug,例如备份目录没有创建、输出信息中的转义字符串没有显示等等。

查看全文

简洁的 Bash Programming 技巧(三)

这是简洁的 Bash Programming 技巧系列的第三篇文章,这一系列的文章专门介绍Bash编程中一些简洁的技巧,帮助大家提高平时 Bash 编程的效率。有兴趣的同学可以回顾下之前的两篇文章(一)续篇

1. 替换语法${parameter/pattern/string}的妙用

${parameter/pattern/string}将parameter中匹配pattern的部分替换成string,例如下面的例子将字符串中的e替换成x:

$ str="three"
$ echo "${str/e/x}"   # thrxe

如果pattern部分以/开头,表示替换parameter中所有匹配的内容,例如:

$ str="three"
$ echo "${str//e/x}"  # thrxx

如果pattern部分以#开头,表示仅当parameter开始处匹配pattern的时候替换,例如:

str="three"
$ echo "${str/#e/x}" # three
$ echo "${str/#t/x}" # xhree

与此对应地是,如果pattern部分以%开头,表示仅当parameter结尾处匹配pattern的时候替换,例如:

$ str="three"
$ echo "${str/%e/x}" # threx

如果string部分为空,匹配pattern的部分被删除(替换为空),例如:

$ str="three"
$ echo "${str/h/}"  # tree

查看全文

1 2 3 4 5