《Linux命令行与shell脚本编程大全》第11章笔记(上)

本篇内容均摘自《Linux命令行与shell脚本编程大全》,个人认为需要重点学习的章节。【免费】Linux命令行与Shell脚本编程大全 第3版 PDF全本 21MB 百度网盘下载 - 今夕是何夕 - 博客园

使用多个命令

shell脚本的关键在于输入多个命令并处理每个命令的结果,甚至需要将一个命令的结果传给另一个命令。 shell可以让你将多个命令串起来,一次执行完成。如果要两个命令一起运行,可以把它们放在同一行中,彼此间用分号隔开。

$ date ; who
Mon Feb 21 15:36:09 EST 2014
Christine tty2 2014-02-21 15:26

这个简单的脚本只用到了两个bash shell命令。 date命令先运行,显示了当前日期和时间,后面紧跟着who命令的输出,显示当前是谁登录到了系统上。使用这种办法就能将任意多个命令串连在一起使用了,只要不超过最大命令行字符数255就行。这种技术对于小型脚本尚可,但它有一个很大的缺陷:每次运行之前,你都必须在命令提示符下输入整个命令。可以将这些命令组合成一个简单的文本文件,这样就不需要在命令行中手动输入了。在需要运行这些命令时,只用运行这个文本文件就行了。


创建 shell 脚本文件

要将shell命令放到文本文件中,首先需要用文本编辑器(参见第10章)来创建一个文件,然后将命令输入到文件中。在创建shell脚本文件时,必须在文件的第一行指定要使用的shell。其格式为:

#!/bin/bash

在通常的shell脚本中,井号( #)用作注释行。 shell并不会处理shell脚本中的注释行。然而,shell脚本文件的第一行是个例外, #后面的惊叹号会告诉shell用哪个shell来运行脚本(是的,你可以使用bash shell,同时还可以使用另一个shell来运行你的脚本)。在指定了shell之后,就可以在文件的每一行中输入命令,然后加一个回车符。之前提到过,注释可用#添加。例如:

#!/bin/bash
# This script displays the date and who's logged on
date
who

这就是脚本的所有内容了。可以根据需要,使用分号将两个命令放在一行上,但在shell脚本中,你可以在独立的行中书写命令。 shell会按根据命令在文件中出现的顺序进行处理。还有,要注意另有一行也以#开头,并添加了一个注释。 shell不会解释以#开头的行(除了以#!开头的第一行)。留下注释来说明脚本做了什么,这种方法非常好。当两年后回过来再看这个脚本时,你还可以很容易回忆起做过什么。将这个脚本保存在名为test1的文件中,基本就好了。在运行新脚本前,还要做其他一些事。现在运行脚本,结果可能会叫你有点失望。

$ test1
bash: test1: command not found

你要跨过的第一个障碍是让bash shell能找到你的脚本文件。如第6章所述, shell会通过PATH环境变量来查找命令。快速查看一下PATH环境变量就可以弄清问题所在。

$ echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/user/bin

PATH环境变量被设置成只在一组目录中查找命令。要让shell找到test1脚本,只需采取以下两种作法之一:
1.将shell脚本文件所处的目录添加到PATH环境变量中;2.在提示符中用绝对或相对文件路径来引用shell脚本文件。

在这个例子中,我们将用第二种方式将脚本文件的确切位置告诉shell。记住,为了引用当前目录下的文件,可以在shell中使用单点操作符。

$ ./test1
bash: ./test1: Permission denied

现在shell找到了脚本文件,但还有一个问题。 shell指明了你还没有执行文件的权限。快速查看一下文件权限就能找到问题所在。

$ ls -l test1
-rw-rw-r-- 1 user user 73 Sep 24 19:56 test1

在创建test1文件时, umask的值决定了新文件的默认权限设置。由于umask变量在Ubuntu中被设成了022(参见第7章),所以系统创建的文件只有文件属主和属组才有读/写权限。下一步是通过chmod命令(参见第7章)赋予文件属主执行文件的权限。

$ chmod u+x test1
$ ./test1
Mon Feb 21 15:38:19 EST 2014

成功了!现在万事俱备,只待执行新的shell脚本文件了。

显示消息

大多数shell命令都会产生自己的输出,这些输出会显示在脚本所运行的控制台显示器上。很多时候,你可能想要添加自己的文本消息来告诉脚本用户脚本正在做什么。可以通过echo命令来实现这一点。如果在echo命令后面加上了一个字符串,该命令就能显示出这个文本字符串。

$ echo This is a test
This is a test

注意,默认情况下,不需要使用引号将要显示的文本字符串划定出来。但有时在字符串中出现引号的话就比较麻烦了。

$ echo Let's see if this'll work
Lets see if thisll work

echo命令可用单引号或双引号来划定文本字符串。如果在字符串中用到了它们,你需要在文本中使用其中一种引号,而用另外一种来将字符串划定起来。

$ echo "This is a test to see if you're paying attention"
This is a test to see if you're paying attention
$ echo 'Rich says "scripting is easy".'
Rich says "scripting is easy".

所有的引号都可以正常输出了。可以将echo语句添加到shell脚本中任何需要显示额外信息的地方。

$ cat test1
#!/bin/bash
# This script displays the date and who's logged on
echo The time and date are:
date
echo "Let's see who's logged into the system:"
who

当运行这个脚本时,它会产生如下输出。

$ ./test1
The time and date are:
Mon Feb 21 15:41:13 EST 2014
Let's see who's logged into the system:
Christine tty2 2014-02-21 15:26

很好,但如果想把文本字符串和命令输出显示在同一行中,该怎么办呢?可以用echo语句的-n参数。只要将第一个echo语句改成这样就行:

echo -n "The time and date are: "

你需要在字符串的两侧使用引号,保证要显示的字符串尾部有一个空格。命令输出将会在紧接着字符串结束的地方出现。现在的输出会是这样:

$ ./test1
The time and date are: Mon Feb 21 15:42:23 EST 2014
Let's see who's logged into the system:
Christine tty2 2014-02-21 15:26

使用变量

运行shell脚本中的单个命令自然有用,但这有其自身的限制。通常你会需要在shell命令使用其他数据来处理信息。这可以通过变量来实现。变量允许你临时性地将信息存储在shell脚本中,以便和脚本中的其他命令一起使用。本节将介绍如何在shell脚本中使用变量。

1.环境变量
shell维护着一组环境变量,用来记录特定的系统信息。比如系统的名称、登录到系统上的用户名、用户的系统ID(也称为UID)、用户的默认主目录以及shell查找程序的搜索路径。可以用set命令来显示一份完整的当前环境变量列表。

$ set
BASH=/bin/bash
[...]
HOME=/home/Samantha
HOSTNAME=localhost.localdomain
HOSTTYPE=i386
IFS=$' \t\n'
IMSETTINGS_INTEGRATE_DESKTOP=yes
IMSETTINGS_MODULE=none
LANG=en_US.utf8
LESSOPEN='|/usr/bin/lesspipe.sh %s'
[...]

在脚本中,你可以在环境变量名称之前加上美元符( $)来使用这些环境变量。下面的脚本演示了这种用法。

$ cat test2
#!/bin/bash
# display user information from the system.
echo "User info for userid: $USER"
echo UID: $UID
echo HOME: $HOME

这里的USER、 UID和HOME环境变量用来显示已登录用户的有关信息。脚本输出如下:

$chmod u+x test2
$ ./test2
User info for userid: Samantha
UID: 1001
HOME: /home/Samantha

注意, echo命令中的环境变量会在脚本运行时替换成当前值。另外,在第一个字符串中可以将$USER系统变量放置到双引号中,而shell依然能够知道我们的意图。但采用这种方法也有一个问题。看看下面这个例子会怎么样。

$ echo "The cost of the item is $15"
The cost of the item is 5

显然这不是我们想要的。只要脚本在引号中出现美元符,它就会以为你在引用一个变量。在这个例子中,脚本会尝试显示变量$1(但并未定义),再显示数字5。要显示美元符,你必须在它前面放置一个反斜线。

$ echo "The cost of the item is \$15"
The cost of the item is $15

看起来好多了。反斜线允许shell脚本将美元符解读为实际的美元符,而不是变量。下一节将会介绍如何在脚本中创建自己的变量。

[说明]你可能还见过通过${variable}形式引用的变量。变量名两侧额外的花括号通常用来帮助识别美元符后的变量名。

2.用户变量
除了环境变量, shell脚本还允许在脚本中定义和使用自己的变量。定义变量允许临时存储数据并在整个脚本中使用,从而使shell脚本看起来更像一个真正的计算机程序。用户变量可以是任何由字母、数字或下划线组成的文本字符串,长度不超过20个。用户变量区分大小写,所以变量Var1和变量var1是不同的。这个小规矩经常让脚本编程初学者感到头疼。使用等号将值赋给用户变量。在变量、等号和值之间不能出现空格。这里有一些给用户变量赋值的例子。
var1=10
var2=-57
var3=testing
var4="still more testing"
shell脚本会自动决定变量值的数据类型。在脚本的整个生命周期里, shell脚本中定义的变量会一直保持着它们的值,但在shell脚本结束时会被删除掉。与系统变量类似,用户变量可通过美元符引用。

$ cat test3
#!/bin/bash
# testing variables
days=10
guest="Katie"
echo "$guest checked in $days days ago"
days=5
guest="Jessica"
echo "$guest checked in $days days ago"

运行脚本会有如下输出。

$ chmod u+x test3
$ ./test3
Katie checked in 10 days ago
Jessica checked in 5 days ago

变量每次被引用时,都会输出当前赋给它的值。重要的是要记住,引用一个变量值时需要使用美元符,而引用变量来对其进行赋值时则不要使用美元符。通过一个例子你就能明白我的意思。

$ cat test4
#!/bin/bash
# assigning a variable value to another variable
value1=10
value2=$value1
echo The resulting value is $value2

在赋值语句中使用value1变量的值时,仍然必须用美元符。这段代码产生如下输出。

$ chmod u+x test4
$ ./test4
The resulting value is 10

要是忘了用美元符,使得value2的赋值行变成了这样:

value2=value1

那你会得到如下输出:

$ ./test4
The resulting value is value1

没有美元符, shell会将变量名解释成普通的文本字符串,通常这并不是你想要的结果。

3.命令替换
shell脚本中最有用的特性之一就是可以从命令输出中提取信息,并将其赋给变量。把输出赋给变量之后,就可以随意在脚本中使用了。这个特性在处理脚本数据时尤为方便。有两种方法可以将命令输出赋给变量:
(1) 反引号字符( `)(2)()格式。要注意反引号字符,这可不是用于字符串的那个普通的单引号字符。由于在shell脚本之外很少用到,你可能甚至都不知道在键盘什么地方能找到这个字符。但你必须慢慢熟悉它,因为这是许多shell脚本中的重要组件。提示:在美式键盘上,它通常和波浪线( ~)位于同一键位。命令替换允许你将shell命令的输出赋给变量。尽管这看起来并不那么重要,但它却是脚本编程中的一个主要组成部分。
要么用一对反引号把整个命令行命令围起来:

testing='date'

要么使用$()格式:

testing=$(date)

shell会运行命令替换符号中的命令,并将其输出赋给变量testing。注意,赋值等号和命令替换字符之间没有空格。这里有个使用普通的shell命令输出创建变量的例子。

$ cat test5
#!/bin/bash
testing=$(date)
echo "The date and time are: " $testing

变量testing获得了date命令的输出,然后使用echo语句显示出它的值。运行这个shell脚本生成如下输出:

$ chmod u+x test5
$ ./test5
The date and time are: Mon Jan 31 20:23:25 EDT 2014

这个例子毫无吸引人的地方(也可以干脆将该命令放在echo语句中),但只要将命令的输出放到了变量里,你就可以想干什么就干什么了。下面这个例子很常见,它在脚本中通过命令替换获得当前日期并用它来生成唯一文件名。

#!/bin/bash
# copy the /usr/bin directory listing to a log file
today=$(date +%y%m%d)
ls /usr/bin -al > log.$today

today变量是被赋予格式化后的date命令的输出。这是提取日期信息来生成日志文件名常用的一种技术。 +%y%m%d格式告诉date命令将日期显示为两位数的年月日的组合。

$ date +%y%m%d
140131

这个脚本将日期值赋给一个变量,之后再将其作为文件名的一部分。文件自身含有目录列表的重定向输出(将在11.5节详细讨论)。运行该脚本之后,应该能在目录中看到一个新文件。

-rw-r--r-- 1 user user 769 Jan 31 10:15 log.140131

目录中出现的日志文件采用$today变量的值作为文件名的一部分。日志文件的内容是/usr/bin目录内容的列表输出。如果脚本在明天运行,日志文件名会是log.140201,就这样为新的一天创建一个新文件。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,380评论 0 5
  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,744评论 0 10
  • 本文是对Linux shell编程的一个学习比较,共包括如下章节的内容: 概述 基本语法 结构化语句 函数 小结 ...
    我是老薛阅读 830评论 0 5
  • 特别说明:以下内容来自简书,链接为原文出处,一切权益归原作者所有,在此感谢原作者的分享,大家可以点击以下链接查看原...
    沈祥佑阅读 553评论 0 4
  • 用了caffe有一段时间了,感觉自己写shell脚本的能力有待提高,特地从菜鸟笔记处系统的看了一遍,其实学习基础就...
    yichen_china阅读 1,822评论 2 30