Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合。
Shell可以直接使用在win/Unix/Linux上面,并且可以调用大量系统内部的功能来解释执行程序,如果熟练掌握Shell脚本,可以让我们操作计算机变得更加轻松,也会节省很多时间。
Shell不是具体哪一款程序,是一类程序的统称,这些程序只要是能够按照用户的要求去调用操作系统的接口,就可以称之为Shell程序.
linux发展至今,有许多shell程序,其中一款软件叫做bash。
1.1 基础命令1.1.2 找出登录人员:who命令
#获取当前已登录系统中的所有用户的信息 #当用户登录熊同事,UNIX系统会为用户所在终端或网络设备分配一个唯一的标识数字,这个数字就是tty编号 who
1.1.3 回显字符:echo命令
echo命令会在终端打印出(或者说回显)你在行中输入的所有内容,且echo会将单词间多余的空白字符压缩,通常会忽略多余的空白字符。
echo this is test
echo ? #打印出一个字母的文件 echo a? #打印出以a开头的两个字母 echo ?? #打印出两个字母的文件 echo ??* #打印出两个字母以上的所有文件 echo * #使用文件名替换,列出所有文件1.2 使用文件
UNIX系统只识别三种基本类型的文件:普通文件、目录文件和特殊文件。
1.2.3 统计文件中单词数量:wc命令
wc命令可以获得文件中的行数、单词数和字符数。需要将待统计的文件名作为该命令的参数。
// 命令
wc [参数] [文件名]
// 命令选项(参数)
l 统计文件包含的行数
c 统计文件中包含的字符数
w 统计文件中包含的单词数
1.3.1 主目录和路径名
按照惯例,【…】指向当前目录的上一级目录,也称为父目录。
另一种惯用写法是单点号【.】,他总是引用当前目录。
1.4.1 星号
Shell有一个强大的特性:文件名的替换。Shell会自动将模式【*】替换成当前目录下能够匹配到的所有文件名。
1.4.2 匹配单个字符
星号(*)能够匹配零个或多个字符,也就是说,x星能够匹配文件x,也能够匹配x1、x2、xabc等。问号(?)仅能匹配单个字符。
破折号(-)指定一个字符的逻辑范围。例如,[0-9]能够匹配字符0~9。在指定字符范围的时候,唯一的限制就是第一个字符在字母表上的必须位于最后一个字符之前。
1.5.1 文件名中的空格
有两种解决办法:使用反斜杠将所有空格进行转义,或者将整个文件名放在引号中,让Shell指导这是一个包含了空格的单词,并非多个单词。
例:
cat "my test document" cat "mytestdocument"1.6 标准输入/输出和I/O重定向
1.6.1 标准输入和标准输出
UNIX命令可以使用文件或上一条命令的输出作为其输入,也可以将其输出发送给另一条命令或其它程序。这个概念极其重要。
Ctrl+d,表示数据输入完毕。
1.6.2 输出重定向
将发送到标准输出的命令输出转移到文件中,即叫做输出重定向。
如果将【>file】放置在能够将输出写入到标准输出上的命令之后,那么该命令的输出就会被写入到文件【file】中:
#使who的输出结果被写入到文件users中 who > users
注意:这个不会有任何输出内容出现,因为输出已经从默认的标准输出设备(终端)重定向到了指定文件中。
如果命令的输出被重定向到某个文件,而这个文件中之前已经有了内容存在,那么这个已有的内容会被重写。
当使用字符【>>】时表示另一种类型的输出重定向。这组字符使得命令的标准输出内容被追加到指定文件的现有内容之后,文件中先前的内容并不会丢失,新的输出只不过被添加到尾部而已。
例:
#将file1的内容追加到file2之后 cat file1 >> file2
1.6.3 输入重定向
正如命令的输出可以被重定向到文件中,文件也可以被重定向命令的输入中。小于号【<】则被作为输入重定向符号。只有哪些从标准输入中接收输入的指令擦能够使用这种方法将文件重定向到其输入中。
1.7 管道1.7.1 管道
UNIX能够将两个命令“连接”在一起,这种连接叫做管道,它可以将一个命令的输出直接作为另一个命令的输入。
管道使用字符【|】表示,被放置在两个命令之间。例如,在【who】和【wc -l】之间创建一个管道,可以输入:
who | wc -l
管道可以在任意两个程序间创建,前提是第一个程序会将输出写入到标准输出,第二个程序会从标准输入中读取输入。
1.7.1 过滤器
可以从标准输入中接收输入,对输入数据进行处理,然后将结果写入标准输出。总的来说就是用来在管道中修改其他程序输出的程序。
cat、sort都可以作为过滤器。
ls、who、date、cd、pwd、echo、rm、mv、及cp并没有从标准输入中读取输入,不是过滤器。
1.9.1 在一行中输入多个命令
如果在一行中输入多个命令,只需要使用分号作为命令之间的分隔符就行。
1.9.3 ps命令
ps命令能够给出系统中所运行的进程信息。
如果配合【-f】选项,ps会打印出更多的进程信息,包括父进程ID(PPID)、进程开始时间(STIME)及其他命令参数。
2.什么是Shell 2.1 内核和实用工具UNIX系统在逻辑上被划分为两个不同的部分:内核和实用工具(Utility),通常来说,所有访问都要经由Shell,Shell是一个实用工具程序,它作为登录过程的一部分被载入到内存中执行。
2.3 在Shell中输入命令重要的要认识到Shell是一个程序,在系统中没有什么特权。
2.4 Shell的职责(1)程序执行
(2)变量及文件明替换
(3)I/O重定向
(4)管道
(5)环境控制
(6)解释型编程语言
3.常备工具 3.1 正则表达式正则表达式给出了一种便捷、一致的方式来指定待匹配的模式。
Shell认为【?】能够匹配任意单个字符,而在正则表达式中(regular expression,通常简写为regex)则是使用点号(.)来实现相同的效果。
3.1.1 匹配任意字符:点号(.)
正则表达式 r. #可以匹配r以及任意单个字符
正则表达式 .x. #可以匹配由任意两个字符包围的x,这两个字符不必相同
正则表达式:查找功能 / ... /
注:编辑器ed是一个旧式的行编辑器,一直存在与Linux中
ed命令正则表达式测试:
ed temp.txt #使用ed编辑器打开文件,然后终端后会打印出文件中总的字符数
1,$p #打印出全部行,【p】为打印命令,【$】为范围限定符,
#最基本的范围限定符就是1,$,这表示从文件的第一行到最后一行
/ ... / #表示查找由空格包围的3个字符
/ #表示重复最后一次查询(继续搜索)
1,$s/p.o/XXX/g #将所有的p.o修改成XXX,【s】为替换命令,【g】表示执行全局替换
3.1.2 匹配行首:脱字符(^)
脱字符^作为正则表达式的第一个字符,用来匹配行首位置
/the/ #表示查找the /^the/ #表示查找以the开头的行 1,$s/^/>>/ #在每一行的行首插入>> 1,$s/^/ / #在每一行的行首插入4个空格
3.1.3 匹配行尾:美元符号($)
点号可以匹配任意字符,因此正则表达式【$】匹配的是行尾的任意字符(包括点号)。
如何匹配点号?一般而言,如果你想匹配任何对于正则表达式来说有特殊含义的字符,可以在该字符前加一个反斜杠()来去除其特殊含义。
.$ #匹配以点号结尾的行
^. #匹配以点号开头的行
#将反斜线作为普通字符,可以使用连续两个反斜线【\】
/.$/ #搜索以点号结尾的行
1,$s/..$// #删除每行最后的两个字符
^$ #匹配空行
^ $ #匹配由单个空格组成的行
3.1.4 匹配字符组:【…】
[tT]he #匹配小写或大写的t,然后是字符the /[tT]he/ #查找the或The 1,$s/aeiouAEIOU//g #所有的元音字母 #可以在中括号内使用字符范围来表示,具体的写法师使用连接符(-)来分隔起始字符与终止字符 [123456789] 或 [0-9] [A-Z] #匹配大写字母 [A-Za-z] #匹配大写或小写字母 /^[A-Z]/ #找出以大写字母起始的行
在ed编辑器中,像*、.、[…]、$和^这类正则表达式序列仅在搜索字符串中有意义,在替换字符串中没有任何特殊含义。
如果脱字符(^)是左中括号后的第一个字符,那么所匹配内容的意义就相反了(相比之下,Shell使用!来实现相同的效果)
[^A-Z] #匹配除大写字母以外的任意字符 [^A-Za-z] #匹配任意非字母字符
3.1.5 匹配零个或多个字符:星号(*)
+可用于匹配一次或多次出现在其之前的表达式,因此以下两种表达方式在功能上没有什么不同
XX* #能够匹配到X以及跟随在其后的零个或多个连续的X XXX* #能匹配至少两个连续的X X+
1,$s/ */ / #将多个空格修改成单个空格 .* #常用于指定零个或多个任意字符,记住,正则表达式匹配的是符合模式的最长字符串,因此,匹配的总是整个文本行
正则表达式 1,$s/e.*e/+++/ #将一行中第一个e到最后一个e之间的全部字符(包括首尾的e在内)替换成+++ [A-Za-z][A-Za-z]* #匹配后面跟着零个或多个字母字符的那些字母字符 []a-z] #能够匹配右中括号或小写字母
3.1.6 匹配固定次数的子模式:{…}
通用来精确指定需要匹配的字符数量:
{min,max} #min指定了待匹配正则表达式需要出现的最小次数,max指定了要出现的最大次数。
#并注意,必须使用反斜线对花括号进行转义
X{1,10} #匹配1到10个连续的X
几种特殊情况:
{10} #花括号中只有一个数字,表明此正则表达四必须匹配的次数
.{10} #能够匹配10个任意字符
1,$s/^.{10}// #删除每行的前10个字符
1,$s/.{5}$// #删除每行后5个字符,注意,不是5个字符的,无法满足匹配条件,不做任何修改
#如果花括号中的单个数字后紧跟着一个逗号,则表示之前的正则表达式至少应该匹配的次数
+{5,} #能够至少匹配5个连续加号,
3.1.7 保存已匹配的字符:(…)
要想引用已经由正则表达式匹配到的字符,可以将这部分正则表达式放在由反斜线转义过得括号里。这些被捕获到的字符会被保存在由正则表达式解析器预定义好的叫做寄存器的变量中,其编号从1到9。
#能够匹配文本行中的第一个字符并将其保存在寄存器1中 ^(.) #要想检索保存在某个寄存器中的字符,使用 n (其中n是从1到9的数字) ^(.)1 #首先匹配文本行中的第一个字符并将其保存在寄存器1中,然后匹配保存在寄存器1中的内容(1指定的) #这个正则表达式的最终效果就是能够匹配一行中头两个相同的字符。 ^(.).*1$ #能够匹配行首字符(^.)和行尾字符(1$)相同的所有的行。首尾字符之间的所有字符有.*匹配
连续出现的(…)可以将其匹配的内容分配给后续的多个寄存器。例:
#文本行中的前3个字符会保存在寄存器1中,接下来3个字符会保存在寄存器2中 ^(...)(...) #能够匹配到一个长度为12个字符的字符串,其中地1~3个字符和第10~12个字符一样,第4~6个字符和第7~9个字符一样 ^(...)(...)21
在ed中使用替换命令时,寄存器也可以作为替换字符串中的一部分引用。
1,$s/(.*) (.*)/2 1/ #交换两个字段3.2 cut
该命令在从数据文件或命令输出中提取(切出)各种字段的时候非常方便。
cut -cchars file
其中,“chars”指定了你想从file中的每行内提取哪些字符(依据位置)包含:
(1)单个数字;如-c5,可以从输入的每行中提取第5个字符
(2)以逗号分隔的数字列表;如,-c1,13,50,可以提取第1个、第13个、第50个字符
(3)连接符分隔的数字范围;如-c20-50,可以提取第20~50个字符
cut -c5- data #提取从自定位置到行尾的所有字符,并将结果写入标准输出
如果没有指定file,cut会从标准输入中读取输入,这意味着你可以在管道中将cut作为过滤器使用。
可以利用cut从文本行中提取不同位置上的字符,如下:
who | cut -c1-8,18- #提取第1~8个字符(用户名),然后提取第18个到行尾的字符(登录时间)
# 命令
cut [参数] [文件名]
# 命令选项(参数),解决非固定格式数据文件
-d 指定字段分隔符
-f 指定待提取的字段
cut -d: -f1,6 /etc/passwd #表示提取出以“:”分隔行第一个字段和第6个字段
如果在不使用-d选项的情况下用cut命令从文件中提取字段,则使用制表符作为默认的字段分隔符,而不是空格。
如果字段是由制表符分隔的,可以使用cut的-f选项:
cut -f1 phonebook #提取文件中的第一个字段
拓展:制表符
制表符即相当于键盘上的 Tab键(Q的左方,Caps lock的上方)
在格式控制输出中用“t”表示
相当于回车在printf中用“n”表示通常用于将输出对齐
如何知道字段是有空格还是由制表符分隔的?
(1)试错法
(2)命令:
sed -n 1 file
如果字段是由制表符分隔的,在制表符的位置上显示:t
3.3 pastepaste 命令的效果和cut相反;它不是拆分行,而是合并行。该命令的一般格式为:
paste files
由files指定的每个文件中对应的行被“粘贴”或合并在一起,形成一行,然后写入到标准文件中(两者之间由制表符分隔)。连接符“-”可以用在files中,将输入源指定为标准输入。
# 命令
paste [参数] [列前文件名] [列后文件名]
# 命令选项(参数)
-d 指定单个分隔符,该分隔符用来分隔粘贴的所有字段
-s 指定paste只能从同一个文件中粘贴行,不管其他文件,如果指定了单个文件,其效果是将该文件中所有的行合并到一 起,彼此之间用制表符分隔(或者是由-d选项指定的分隔符)
例: paste -d'+' names address numbers #将分隔符放在单引号中总是最安全的办法 paste -s names #粘贴names文件中的所有行 ls | paste -d' ' -s - #粘贴ls命令的输入,使用空格作为分隔符



