C 语言简介
历史
C 语言最初是作为 Unix 系统的开发工具而发明的。
1969年,美国贝尔实验室的肯·汤普森(Ken
Thompson)与丹尼斯·里奇(Dennis Ritchie)一起开发了 Unix 操作系统。Unix
是用汇编语言写的,无法移植到其他计算机,他们决定使用高级语言重写。但是,当时的高级语言无法满足他们的要求,汤普森就在
BCPL 语言的基础上发明了 B 语言。
1972年,丹尼斯·里奇和布莱恩·柯林汉(Brian Kernighan)又在 B
语言的基础上重新设计了一种新语言,这种新语言取代了 B 语言,所以称为 C
语言。
1973年,整个 Unix 系统都使用 C
语言重写。此后,这种语言开始快速流传,广泛用于各种操作系统和系统软件的开发。
1988年,美国国家标准协会(ANSI)正式将 C 语言标准化,标志着 C
语言开始稳定和规范化。
几十年后的今天,C
语言依然是最广泛使用、最流行的系统编程语言之一,Unix 和 Linux
系统现在还是使用 C 语言开发。
C 语言的特点
C 语言能够长盛不衰、广泛应用,主要原因是它有一些鲜明的特点。
(1)低级语 ...
read 命令
用法
有时,脚本需要在执行过程中,由用户提供一部分数据,这时可以使用read命令。它将用户的输入存入一个变量,方便后面的代码使用。用户按下回车键,就表示输入结束。
read命令的格式如下。
1read [-options] [variable...]
上面语法中,options是参数选项,variable是用来保存输入数值的一个或多个变量名。如果没有提供变量名,环境变量REPLY会包含用户输入的一整行数据。
下面是一个例子demo.sh。
12345#!/bin/bashecho -n "输入一些文本 > "read textecho "你的输入:$text"
上面例子中,先显示一行提示文本,然后会等待用户输入文本。用户输入的文本,存入变量text,在下一行显示出来。
123$ bash demo.sh输入一些文本 > 你好,世界你的输入:你好,世界
read可以接受用户输入的多个值。
1234#!/bin/bashecho Please, enter your firstname and lastnamerea ...
Bash 脚本入门
脚本(script)就是包含一系列命令的一个文本文件。Shell
读取这个文件,依次执行里面的所有命令,就好像这些命令直接输入到命令行一样。所有能够在命令行完成的任务,都能够用脚本完成。
脚本的好处是可以重复使用,也可以指定在特定场合自动调用,比如系统启动或关闭时自动执行脚本。
Shebang 行
脚本的第一行通常是指定解释器,即这个脚本必须通过什么解释器执行。这一行以#!字符开头,这个字符称为
Shebang,所以这一行就叫做 Shebang 行。
#!后面就是脚本解释器的位置,Bash
脚本的解释器一般是/bin/sh或/bin/bash。
123#!/bin/sh# 或者#!/bin/bash
#!与脚本解释器之间有没有空格,都是可以的。
如果 Bash
解释器不放在目录/bin,脚本就无法执行了。为了保险,可以写成下面这样。
1#!/usr/bin/env bash
上面命令使用env命令(这个命令总是在/usr/bin目录),返回
Bash 可执行文件的位置。env命令的详细介绍,请看后文。
Shebang
行不是必需的,但是建议加上这行。如果缺少该行 ...
目录堆栈
为了方便用户在不同目录之间切换,Bash 提供了目录堆栈功能。
cd -
Bash
可以记忆用户进入过的目录。默认情况下,只记忆前一次所在的目录,cd -命令可以返回前一次的目录。
12345# 当前目录是 /path/to/foo$ cd bar# 重新回到 /path/to/foo$ cd -
上面例子中,用户原来所在的目录是/path/to/foo,进入子目录bar以后,使用cd -可以回到原来的目录。
pushd,popd
如果希望记忆多重目录,可以使用pushd命令和popd命令。它们用来操作目录堆栈。
pushd命令的用法类似cd命令,可以进入指定的目录。
1$ pushd dirname
上面命令会进入目录dirname,并将该目录放入堆栈。
第一次使用pushd命令时,会将当前目录先放入堆栈,然后将所要进入的目录也放入堆栈,位置在前一个记录的上方。以后每次使用pushd命令,都会将所要进入的目录,放在堆栈的顶部。
popd命令不带有参数时,会移除堆栈的顶部记录,并进入新的堆栈顶部目录(即原来的第二条目录)。
下面是一个例子。
123456789101112 ...
Bash 行操作
简介
Bash 内置了 Readline
库,具有这个库提供的很多“行操作”功能,比如命令的自动补全,可以大大加快操作速度。
这个库默认采用 Emacs 快捷键,也可以改成 Vi 快捷键。
1$ set -o vi
下面的命令可以改回 Emacs 快捷键。
1$ set -o emacs
如果想永久性更改编辑模式(Emacs /
Vi),可以将命令写在~/.inputrc文件,这个文件是 Readline
的配置文件。
1set editing-mode vi
本章介绍的快捷键都属于 Emacs 模式。Vi 模式的快捷键,读者可以参考 Vi
编辑器的教程。
Bash 默认开启这个库,但是允许关闭。
1$ bash --noediting
上面命令中,--noediting参数关闭了 Readline 库,启动的
Bash 就不带有行操作功能。
光标移动
Readline 提供快速移动光标的快捷键。
Ctrl + a:移到行首。
Ctrl + b:向行首移动一个字符,与左箭头作用相同。
Ctrl + e:移到行尾。
Ctrl + f:向行尾移动一个字符,与右箭 ...
Bash 的算术运算
算术表达式
((...))语法可以进行整数的算术运算。
123$ ((foo = 5 + 5))$ echo $foo10
((...))会自动忽略内部的空格,所以下面的写法都正确,得到同样的结果。
123$ ((2+2))$ (( 2+2 ))$ (( 2 + 2 ))
这个语法不返回值,命令执行的结果根据算术运算的结果而定。只要算术结果不是0,命令就算执行成功。
123$ (( 3 + 2 ))$ echo $?0
上面例子中,3 + 2的结果是5,命令就算执行成功,环境变量$?为0。
如果算术结果为0,命令就算执行失败。
123$ (( 3 - 3 ))$ echo $?1
上面例子中,3 - 3的结果是0,环境变量$?为1,表示命令执行失败。
如果要读取算术运算的结果,需要在((...))前面加上美元符号$((...)),使其变成算术表达式,返回算术运算的值。
12$ echo $((2 + 2))4
((...))语法支持的算术运算符如下。
+:加法
-:减法
*:乘法
/:除法(整除)
%:余数
**:指数
++:自增运算(前缀或后缀)
- ...
字符串操作
本章介绍 Bash 字符串操作的语法。
字符串的长度
获取字符串长度的语法如下。
1${#varname}
下面是一个例子。
123$ myPath=/home/cam/book/long.file.name$ echo ${#myPath}29
大括号{}是必需的,否则 Bash
会将$#理解成脚本的参数个数,将变量名理解成文本。
12$ echo $#myvar0myvar
上面例子中,Bash
将$#和myvar分开解释了。
子字符串
字符串提取子串的语法如下。
1${varname:offset:length}
上面语法的含义是返回变量$varname的子字符串,从位置offset开始(从0开始计算),长度为length。
123$ count=frogfootman$ echo ${count:4:4}foot
上面例子返回字符串frogfootman从4号位置开始的长度为4的子字符串foot。
这种语法不能直接操作字符串,只能通过变量来读取字符串,并且不 ...
Bash 变量
简介
Bash 变量分成环境变量和自定义变量两类。
环境变量
环境变量是 Bash 环境自带的变量,进入 Shell
时已经定义好了,可以直接使用。它们通常是系统定义好的,也可以由用户从父
Shell 传入子 Shell。
env命令或printenv命令,可以显示所有环境变量。
123$ env# 或者$ printenv
下面是一些常见的环境变量。
BASHPID:Bash 进程的进程 ID。
BASHOPTS:当前 Shell
的参数,可以用shopt命令修改。
DISPLAY:图形环境的显示器名字,通常是:0,表示
X Server 的第一个显示器。
EDITOR:默认的文本编辑器。
HOME:用户的主目录。
HOST:当前主机的名称。
IFS:词与词之间的分隔符,默认为空格。
LANG:字符集以及语言编码,比如zh_CN.UTF-8。
PATH:由冒号分开的目录列表,当输入可执行程序名后,会搜索这个目录列表。
PS1:Shell 提示符。
PS2: 输入多行命令时,次要的 Shell 提示符。
PWD:当前工作目录。
RANDOM:返回一个0到32767之 ...
引号和转义
Bash 只有一种数据类型,就是字符串。不管用户输入什么数据,Bash
都视为字符串。因此,字符串相关的引号和转义,对 Bash 来说就非常重要。
转义
某些字符在 Bash
里面有特殊含义(比如$、&、*)。
123$ echo $date$
上面例子中,输出$date不会有任何结果,因为$是一个特殊字符。
如果想要原样输出这些特殊字符,就必须在它们前面加上反斜杠,使其变成普通字符。这就叫做“转义”(escape)。
12$ echo \$date$date
上面命令中,只有在特殊字符$前面加反斜杠,才能原样输出。
反斜杠本身也是特殊字符,如果想要原样输出反斜杠,就需要对它自身转义,连续使用两个反斜线(\\)。
12$ echo \\\
上面例子输出了反斜杠本身。
反斜杠除了用于转义,还可以表示一些不可打印的字符。
\a:响铃
\b:退格
\n:换行
\r:回车
\t:制表符
如果想要在命令行使用这些不可打印的字符,可以把它们放在引号里面,然后使用echo命令的-e参数。
12345$ echo a\tbatb$ echo -e "a\tb&q ...
Bash 的模式扩展
简介
Shell
接收到用户输入的命令以后,会根据空格将用户的输入,拆分成一个个词元(token)。然后,Shell
会扩展词元里面的特殊字符,扩展完成后才会调用相应的命令。
这种特殊字符的扩展,称为模式扩展(globbing)。其中有些用到通配符,又称为通配符扩展(wildcard
expansion)。Bash 一共提供八种扩展。
波浪线扩展
? 字符扩展
* 字符扩展
方括号扩展
大括号扩展
变量扩展
子命令扩展
算术扩展
本章介绍这八种扩展。
Bash 是先进行扩展,再执行命令。因此,扩展的结果是由 Bash
负责的,与所要执行的命令无关。命令本身并不存在参数扩展,收到什么参数就原样执行。这一点务必需要记住。
模块扩展的英文单词是globbing,这个词来自于早期的 Unix
系统有一个/etc/glob文件,保存扩展的模板。后来 Bash
内置了这个功能,但是这个名字就保留了下来。
模式扩展与正则表达式的关系是,模式扩展早于正则表达式出现,可以看作是原始的正则表达式。它的功能没有正则那么强大灵活,但是优点是简单和方便。
Bash 允许用户关闭扩展。
...
