UNIX的标准用户界面是命令行,其实就是Shell,它的角色是作为用户和系统最底层之间(内核)的缓冲带。Shell就是一个程序,读入用户输入的命令,将其转换成系统更易于理解的形式。 -UNIX/Linux/OS X中的Shell编程
每天的工作都离不开命令行,其实也没怎么专门学习过,知道的也就那几个命令,刚好看到这本书,记录一下之前不知道的,没怎么用过的,但是学会了以后能提高效率的,看似b格很高的命令,方便忘记的时候查找,面向命令行开发。
第1章 基础概述
1.2.2 显示文件内容:cat命令
你可以使用cat(concatenate)命令来查看文件的内容,cat的参数是待检查的文件名:
cat fileName
1.2.5 复制文件:cp命令
可以使用cp命令来复制文件。该命令的第一个参数是要复制的文件名(称为源文件),第二个参数是要复制为的文件名(称为目标文件):
##你可以像下面这样将文件names复制为saved_names
cp names saved_names
cp命令可以用来在目录间复制文件。例如,你可以将programs目录下的文件names复制到misc目录下:
cp prorams/names misc/names
如果目标文件打算采用和源文件相同的名字(在不同的目录中),只需要指定目标目录作为第二个参数就行了:
cp prorams/names misc
你可以一次向目录中复制多个文件,只需要将多个文件名放在目标目录之前就可以了:
##执行下列命令会将文件a、b和c以相同的名字复制到misc目录中
cp a b c d misc
要想将文件从其他目录中复制到你当前所处的位置上并采用相同的名字,可以使用.作为当前目录的简写:
##将programs目录下的文件a、b、c、d复制到当前目录下
cp prorams/a b c d .
1.2.6 文件重命名:mv命令
可以使用mv(move)命令重命名文件。mv命令的参数形式和cp命令一样。第一个参数是待重命名的文件,第二个参数是文件的新名字。
##将文件oldName更名为newName,可以使用下列命令
mv oldName newName
注意,在执行mv或cp命令时,如果目标文件不存在则cp命令会先创建一个新文件,然后把内容复制进去,如果存在与目标文件同名的文件,则同名文件之前的内容会被覆盖,内容就丢失了。
1.2.7 删除文件:rm命令
rm命令可以从系统中删除文件。rm命令的参数就是要删除的文件:
rm fileName
你可以使用rm命令一次删除多个文件,只需要将这些文件在命令行上列出就可以了。
##删除文件a、b和c
rm a b c
要想将文件从其他目录中复制到你当前所处的位置上并采用相同的名字,可以使用“.”作为当前目录的简写。
1.3.3 更改目录:cd命令
这个是大家用的比较多的一个命令,重点记录一些容易搞混的地方:
-
移动到上一级目录最简单的方法:
cd .. -
移动到上两级目录:
cd ../.. -
返回主目录最简单的方法,就是输入不带有任何参数的cd命令。无论你当前处于文件系统中的什么位置,这种用法都可以将你直接带回主目录中:
cd
1.3.4 ls命令的更多用法
如果你将其中一个目录名称提供给ls命令,就可以得到该目录中的内容列表:
ls documents
ls documents/subDocuments
ls -l选项(字母l),可以给出目录下文件更详细的描述信息,用来确定某个特定文件是否为目录。下面是ls命令的-l选项的输出:
第一行显示出了所列出文件占用的存储块数。后续每行第一个字符指明了文件类型:目录是d,文件是-(掘金这个编辑器不知道为啥识别不了减号的加粗),特殊文件是b、c、l或 p。
接下来的9个字符定义了文件或目录的访问权限。访问模式(access mode)应用于文件所有者(前3个字符)、与文件所有者同组的其他用户(接下来的3个字符)以及系统中的其他用户(最后3个字符)。 然后会显示出链接数、文件所有者、文件所属组、文件大小(其中包含了多少个字符)以及文件最后的修改时间、最后一部分信息是文件名。
1.3.5 创建目录:mkdir命令
mkdir命令可用于创建目录。该命令的参数就是你要创建的目录名:
mkdir dirName
1.3.9 删除目录:rmdir命令
rmdir命令可以用来删除目录。如果指定的目录中包含任何文件和子目录,rmdir不会继续进行处理,这样就避免了误删文件的可能。
rmdir dirName
还有另外一种删除目录及其内容的方法:使用rm命令的-r选项。r m命令会删除指定的目录以及其中的所有文件(包括目录),因此在使用这条强力命令的时候可得小心。
rm -r dirName
1.4.1 星号
星号(*)能够匹配零个或多个字符,它还可以与其他字符配合使用,以限制所能够匹配到的文件名范围。
##显示文件名以a结尾的文件内容
cat *a
##显示是文件名以a开头的文件内容
cat a*
##显示文件名包含a的文件内容
cat *a*
##能够匹配文件x,也能够匹配`x1、x2、xabc`等
cat x*
1.4.2 匹配单个字符
问号(?)仅能够匹配单个字符。
##能够显示出所有文件名中只有单个字符的文件,实际操作的时候这个命令无效,不知道是不是系统的原因
cat ?
##显示出文件名长度为两个字符且第一个字符是x的所有文件
cat x?
##找出所有文件名长度至少为两个字符的文件
cat ??*
另一种匹配单个字符的方法是在中括号[]中给出待匹配的字符列表。
例如,[abc]能够匹配字符a、b或c。这类似于?,但是允许你选择具体要匹配哪些字符。你可以使用破折号指定一个字符的逻辑范围。例如,[0-9]能够匹配字符0~9,而[f-z]能够匹配字符f~z。可以通过配合使用字符范围以及字符列表来实现复杂的替换。
##能够匹配以字母a~n或者p~z开头的所有文件(或者说得再简单些,就是不以小写字母o开头的文件)
cat [a–np–z]*
如果[之后的第一个字符是!,那么所匹配的内容正好相反。也就是说,匹配中括号内容之外的任意字符。
##匹配小写字母以外的任意字符
cat [!a-z]
1.6.1 标准输入和标准输出
必须在完成最后一行输入后指定文件结尾序列(end-of-file sequence),按照UNIX的惯例,这指的是Ctrl+d,即同时按下Control键(视所使用的键盘不同,也可以是Ctrl键)和d键所产生的序列。
1.6.2 输出重定向
如果将> file放置在能够将输出写入到标准输出上的命令之后,那么该命令的输出就会被写入到文件file中:
##将zhang写入到names文件中,names文件中原有的内容会被覆盖
echo zhang > names
##将wang写入到names文件中,wang会追加在names文件最后,原有内容不会被覆盖
echo wang >> names
##将oldNames文件的内容追加到names文件之后
cat oldNames >> names
##将oldNames和newNames文件的内容追加到names文件之后
cat oldNames newNames > names
1.7 管道
UNIX能够将两个命令“连接”在一起。这种连接叫做管道,它可以将一个命令的输出直接作为另一个命令的输入。管道使用字符|表示,被放置在两个命令之间。
##统计目录中的文件个数
ls | wc -l
1.9.1 在一行中输入多个命令
如果想在一行中输入多个命令,只需要使用分号作为命令之间的分隔符就行了。
##显示出当前时间及当前工作目录
date; pwd
1.9.3 ps命令
ps命令能够给出系统中所运行进程的信息。
ps
##打印出更多的进程信息,包括父进程ID(PPID)、进程开始时间(STIME)及其他命令参数
ps -f
ps命令会打印出4列信息(视系统而定):PID(进程ID);TTY(进程所在的终端号);TIME(以分秒计算的进程所使用的计算机时间);CMD(进程名称)。(上例中的bash进程是登录时所启动的Shell,它使用了9秒钟的计算机时间。)在该命令结束之前,它在输出中都显示为一个运行的进程,因此上例中的进程19880就是ps命令本身。
1.10 命令总结
第2章 什么是Shell
2.1 内核和实用工具
Shell也是一个实用工具程序,它作为登录过程的一部分被载入到内存中执行。
第3章 常备工具
3.1.1 匹配任意字符:点号(.)
##r以及任意单个字符
r.
##任意两个字符包围的x,这两个字符不必相同
.x.
3.1.2 匹配行首:脱字符(^)
如果脱字符^作为正则表达式的第一个字符,它可以匹配行首位置。
##只能够匹配出现在行首的George
^George
3.1.3 匹配行尾:美元符号($)
如同[^]()可以用来匹配行首,美元符号$可以匹配行尾。
##能够匹配出现在行尾的字符序列contents
contents$
##能够匹配出现在行尾的任意字符
.$
##能够匹配以点号结尾的行
\.$
##能匹配以点号开头的行
^\.
##它能够匹配空行
^$
3.1.4 匹配字符组:[...]
字符[和]用来指定封闭其中的字符组中待匹配的某个字符。
##匹配小写或大写的t,然后是字符he
[tT]he
##匹配0到9之间的任意数字
[0-9]
##匹配A到Z之间的任意大写字母
[A-Z]
##匹配大写或小写字母
[a-zA-Z]
如果脱字符^是左中括号后的第一个字符,那么所匹配内容的意义就相反了(相比之下,Shell使用!来实现相同的效果)
##匹配除大写字母以外的任意字符
[^A-Z]
##匹配任何非字母字符
[^a-zA-Z]
3.1.5 匹配零个或多个字符:星号(*)
Shell在文件名替换中使用星号来匹配零个或多个字符。在正则表达式中,星号用于匹配零次或多次出现在其之前的正则表达式元素(这可以是另外的正则表达式),正则表达式匹配的是符合模式的最长的字符串。
##匹配0个或多个大写字母X
X*
##匹配一个或多个大写字母X
XX*
##匹配两个或多个大写字母X
XX+
##用于指定零个或多个任意字符。
.*
##匹配一行中第一个e到最后一个e之间的全部字符(包括首尾的e在内)
e.*e
##匹配后面跟着零个或多个字母字符的那些字母字符
[a-zA-Z][a-zA-Z]*
如果你想在字符组中匹配连接符,必须将其放在左中括号之后(如果其中还有字符^的话,就放在^的后面)或右中括号之前,这样正则表达式引擎才能够正确地理解你的意图。
##匹配单个的连接符或数字字符
[-0-9]
[0-9-]
如果你想匹配一个右中括号的话,就必须将其放在左中括号之后(如果其中还有字符^的话,就放在^的后面)
##匹配右中括号或小写字母
[]a-z]
3.1.6 匹配固定次数的子模式:\{...\}
有一种更为通用的方法可以用来精确地指定需要匹配的字符数量:
\{min,max\}
其中min指定了待匹配的正则表达式需要出现的最小次数,max指定了要出现的最大次数。注意,你必须使用反斜线对花括号进行转义。
##能够匹配1到10个连续的X。只要有可能,正则表达式总是匹配最长的字符序列,因此,如果输入文本中包含8个连续的X,那就匹配这8个X
X\{1,10\}
##匹配长度为4到7之间的字母字符序列
[A-Za-z]\{4,7\}
如果花括号中只有一个数字,这个数字就指明了之前的正则表达式必须匹配的次数:
##能够匹配7个字母字符
[a-zA-Z]\{7\}
##能够匹配10个任意字符
.\{10\}
如果花括号中的单个数字后紧跟着一个逗号,则表示之前的正则表达式至少应该匹配的次数,最多匹配的次数不限。
##能够匹配至少5个连续的加号
+\{5,\}
正则表达式字符表
3.2 cut
该命令在从数据文件或命令输出中提取(切出)各种字段的时候非常方便。其一般格式为:cut -c chars file,chars指定了你想从 file中的每行内提取哪些字符(依据位置)。
##从输入文件每行中提取第5个字符
cut -c5 file
##可以提取第1个、第13个及第50个字符
cut -c1,13,50 file
##可以提取第20~50个字符
cut -c20-50 file
##提取每一行中的第5个字符到行尾的所有字符
cut -c5-
##展示已经登入了系统用户的名字
who | cut -c1-8
当数据是由特定字符分隔的时候,cut命令的-d和-f选项就能派上用场了。-d指定字段分隔符,-f指定待提取的字段。cut命令的形式如下:
cut -d dchar-f fields file
中,dchar是分隔数据中字段的字符,fiedls指定了从file中要提取的字段。字段号从1开始,字段编号的格式与之前讲过的字符位置格式一样(例如,-fl,2,8、-fl-3、-f4-)。
如果字段是由制表符分隔的,可以使用cut的-f选项,你并不需要使用-d选项来制定分隔符,因为cut默认使用的分隔符就是制表符。
该怎么知道字段是由空格还是由制表符分隔的?在终端中输入命令:
sed -n l file
如果字段是由制表符分隔的,在制表符的位置上会显示\t:
3.3 paste
paste命令的效果和cut相反:它不是拆分行,而是合并行。该命令的一般格式为:
paste files
由files指定的每个文件中对应的行被“粘贴”或合并在一起,形成了一行,然后写入到标准输出中。连接符-可以用在files中,将输入源指定为标准输入。
3.3.1-d选项
如果你不希望使用制表符作为输出字段的分隔符,可以通过-d选项来指定:
##用'+'来分隔粘贴的所有字段
paste -d'+' names address numbers
3.3.2-s选项
-s选项告诉paste只从同一个文件中粘贴行,不管其他文件。如果只指定了单个文件,其效果是将该文件中所有的行合并到一起,彼此之间用制表符分隔(或是由-d选项指定的分隔符)。
ls | paste -d' ' -s -
ls的输出通过管道传给了paste,后者将来自标准输入(-)的所有行(-s选项)进行合并,字段之间使用单个空格(-d' ’选项)分隔。
3.4 sed
sed可以用来在管道或命令序列中编辑数据。它是stream editor(流编辑器)的简称。
##将name文件中每行第一个出现的2替换为two
sed 's/2/two/' name
##修改每一行中多次出现的2
sed 's/2/two/g' name
##用空格(//)将第一个空格到本行末尾的所有字符(. *$)全部替换掉
who | sed 's/ .*$//'
上面这个命令并不会修改原始输入文件,要想让更改永久生效,必须将sed的输出重定向到临时文件,然后使用该临时文件替换掉原文件:
sed 's/2/two/' name > temp
##打印name文件的前两行
sed -n '1,2p' name
##打印name文件中包含2的所有行
sed -n '/2/p' name
##删除name文件的前两行
sed '1,2d' name
##删除name文件中包含2的所有行
sed '/2/d' name
更多命令示例:
3.5 tr
过滤器tr可用于转换标准输入中的字符。
##将所有的字符e转换成x
tr e x < filename
##将intro文件中所有的小写字母转换成对应的大写字母
tr '[a-z]' '[A-Z]' < intro