20135202闫佳歆——信息安全系统设计基础第二周学习总结

第二周(9.14-9.20):

 

学习计时:共25小时

读书:10

代码:7

作业:2

博客:6

一、学习目标

了解以下知识:

1)        Linux 系统简介

2)          基本概念及操作

3)          用户及文件权限管理

4)          Linux 目录结构及文件基本操作

5)          环境变量与文件查找

6)          文件打包与解压缩

7)          文件系统操作与磁盘管理

8)          命令执行顺序控制与管道

9)          简单的文本处理

10)    数据流重定向

11)    正则表达式基础

12)    Linux下软件安装

二、学习资源

1. 课程资料:https://www.shiyanlou.com/courses/413   实验一

2. Linux 基础入门:https://www.shiyanlou.com/courses/1(重点,第一次课考核内容全部从这里面出)

3.  Linux命令:en   cn

三、学习方法

1.  进度很重要:必须跟上每周的进度,阅读,练习,问答,项目。我会认真对待每一位同学,请你不要因为困难半途而废。

2. 问答很重要:遇到知识难点请多多提问,这是你的权利更是您对自己负责的义务。问答到博客园讨论小组:http://group.cnblogs.com/103791/

3. 实践很重要:解决书中习题,实践书中实例,完成每周项目,才算真的消化了这本好书。通过实验楼环境或自己安装的虚拟机在实践中进行学习

4. 实验报告很重要:详细记录你完成项目任务的思路,获得老师点评和帮助自己复习。学习完成后在博客园中(http://www.cnblogs.com/)把学习过程通过博客发表,博客标题“信息安全系统设计基础第一周学习总结”

四、学习任务

(提示:请将要求学生完成的任务、测验或思考题列在此处)

1. 重点学习 cheat/find/locate/grep/man/whereis/which/apt-get

   查找帮助文档、各种示例多多练习,这几个命令会贯穿我们整个学习的学习,掌握这几个命令就可以很好学习其他命令了。

2. 这学期需要掌握的命令有ac,apt-get,bzip2,cat,chgrp,chmod,chown,clear,compress,cp,dd,df,diff,du,dump,evn,find,finger,free,grep,gzip,head,kill,less,ln,locate,l,gout,ls,man,mkdir,more,mount,mt,mv,netstat,nslookup,od,passwd,patch,ps,pstop,pwd,rm,shell,sort,ssh,stty,tail,tar,telnet,touch,tree,uname,unzip,vi,vim,whereis,which,who,write等

3. 测试示例:

      
  • 请在虚拟机中安装DDD软件(其他软件)
  •   
  • 请演示怎么判断DDD软件能不能安装
  •   
  • 请查找系统中50M以上的文件
  •   
  • 请查找系统中两天前修改过的且小于5M的文件
  •   
  • 请问如何查找操作系统的信息
  •   
  • 请查找当前目录下所有*.c文件中哪个文件中包含main函数
  •   
  • 请建立一个目录,里面建立两个子文目录,如何一条命令删除三个目录?
  •   
  • 如何把一个目录及子目录拷贝到自己的主目录中
  •   
  • ...

 

、后续学习预告(可选):

Linux下C语言编程基础:

VIM进行编辑

GCC进行编译

GDB进行调试

Make进行自动化

、学习过程

第一节 Linux系统简介

在这一节中我了解了Linux系统的起源和发展,大事记,Unix进化史,和Linux的重要人物,比如Ken Thompson——是C 语言之父和 UNIX 之父;Dennis Ritchie——C 语言之父和 UNIX 之父;Stallman——著名黑客,GNU 创始人,开发了 Emacs、gcc、bash shell;Bill Joy——BSD 开发者;Tanenbaum——Minix 开发者Linus Torvalds——Linux 之父。

我还了解到了Linux和Windows系统的不同之处,在费用、软件支持、安全等方面有了更多的了解。并且知道了学习Linux的正确方式方法和态度。

 

第二节 基本概念及操作

本节实验主要有:

1、实验楼环境介绍 2、常用 Shell 命令及快捷键 3、Linux 使用小技巧

一、Linux 桌面环境介绍

相对于现在的 Windows 系统,UNIX/Linux 本身是没有图形界面的,我们通常在 Unix/Linux 发行版上看到的图形界面实际都只是运行在 Linux 系统之上的一套软件。

X.org相当于一个服务器,实现了客户端功能的桌面环境KDE,GNOME,XFCE,LXDE,实验楼用的是XFCE。

l  终端

常见终端模拟器:gnome-terminal,kconsole,xterm,rxvt,kvt,nxterm 和 eterm,目前我们的实验中的终端程序是 xfce 桌面环境自带的 xfce-terminal。

终端本质上是对应着 Linux 上的   /dev/tty 设备,Linux 的多用户登陆就是通过不同的 /dev/tty 设备完成的,Linux 默认提供了 6 个纯命令行界面的 “terminal”(准确的说这里应该是 6 个   virtual consoles)来让用户登录,在物理机系统上你可以通过使用[Ctrl]+[Alt]+[F1][F6]进行切换,不过在我们的在线实验环境中可能无法切换,因为特殊功能按键会被你主机系统劫持。当你切换到其中一个终端后想要切换回图形界面,你可以按下[Ctrl]+[Alt]+[F7]来完成。【引用自实验楼课程内容】

l  Shell

通常在图形界面中对实际体验带来差异的不是上述的不同发行版的各种终端模拟器,而大都是这个 Shell(壳),有壳就有核,这里的核就是指的 UNIX/Linux 内核,Shell 是指“提供给使用者使用界面”的软件(命令解析器),类似于   DOS 下的   command(命令行)和后来的 cmd.exe。普通意义上的 Shell 就是可以接受用户输入命令的程序。它之所以被称作 Shell 是因为它隐藏了操作系统底层的细节。同样的 Unix/Linux 下的图形用户界面 GNOME 和 KDE,有时也被叫做“虚拟 shell”或“图形 shell”。

在 UNIX/Linux 中比较流行的常见的   Shell 有   bash,zsh,ksh,csh 等等,Ubuntu 终端默认使用的是   bash,默认的桌面环境是 GNOME 或者 Unity(基于 GNOME),但我们的环境中使用的分别是zsh 和 xfce。【引用自教程】

l  命令行操作体验

1)          重要快捷键:

[tab]补全命令,补全目录,补全命令参数等等

[Ctrl+c]强行终止当前程序,不退出终端

[Ctrl+d]  键盘输入结束或退出终端

[Ctrl+s]  暂定当前程序,暂停后按下任意键恢复运行

[Ctrl+z]  将当前程序放到后台运行,恢复到前台为命令fg

[Ctrl+a]  将光标移至输入行头,相当于Home键

[Ctrl+e]  将光标移至输入行末,相当于End键

[Ctrl+k]  删除从光标所在位置到行末

[Alt+Backspace]  向前删除一个单词

[Shift+PgUp] 将终端显示向上滚动

[Shift+PgDn] 将终端显示向下滚动

2)          历史输入命令

↑可以恢复你输入过的指令

3)          通配符

通配符是一种特殊语句,主要有星号(*)和问号(?),用来对对字符串进行模糊匹配(比如文件名,参数名)。当查找文件夹时,可以使用它来代替一个或多个真正字符;当不知道真正字符或者懒得输入完整名字时,常常使用通配符代替一个或多个真正的字符。

                                                                     

这张图就是用星号模糊了文件名的搜索方法。

    

在linux中创建多个类似文件的方法:touch stony_{1..10}_linux.txt

 

Shell 常用通配符:

                                                                                
   

字符

   
   

含义

   
   

*

   
   

匹配 0 或多个字符

   
   

?

   
   

匹配任意一个字符

   
   

[list]

   
   

匹配 list 中的任意单一字符

   
   

[!list]

   
   

匹配 除list 中的任意单一字符以外的字符

   
   

[c1-c2]

   
   

匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z]

   
   

{string1,string2,...}

   
   

匹配 sring1 或 string2 (或更多)其一字符串

   
   

{c2..c2}

   
   

匹配 c1-c2 中全部字符 如{1..10}

   

 

4)          在命令行中获取帮助

需要使用man指令。

输入man ls后:

    

Man中分了八个区段,要查看相应区段的内容,就在 man 后面加上相应区段的数字即可,如 man 3 ls 。

 

通常 man 手册中的内容很多,你可能不太容易找到你想要的结果,不过幸运的是你可以在 man 中使用搜索,/<你要搜索的关键字>,查找到后你可以使用n键切换到下一个关键字所在处,shift+n为上一个关键字所在处。使用Space(空格键)翻页,Enter(回车键)向下滚动一行,或者使用j,k(vim编辑器的移动键)进行向前向后滚动一行。按下h键为显示使用帮助(因为man使用less作为阅读器,实为less工具的帮助),按下q退出。

想要获得更详细的帮助,你还可以使用info命令,不过通常使用man就足够了。如果你知道某个命令的作用,只是想快速查看一些它的某个具体参数的作用,那么你可以使用--help参数,大部分命令都会带有这个参数【引用实验楼教程】,如:

    

 

第三节 用户及文件权限管理

实验介绍

1、Linux 中创建、删除用户,及用户组等操作。

2、Linux 中的文件权限设置。

 

一、Linux 用户管理

1.查看用户

    

输入的第一列表示打开当前伪终端的用户的用户名(要查看当前登录用户的用户名,去掉空格直接使用 whoami 即可)      ,第二列的 pts/0 中 pts 表示伪终端,所谓伪是相对于 /dev/tty 设备而言的,还记得上一节讲终端时的那七个使用 [Ctrl]+[Alt]+[F1]~[F7] 进行切换的 /dev/tty 设备么,这是“真终端”,伪终端就是当你在图形用户界面使用 /dev/tty7 时每打开一个终端就会产生一个伪终端, pts/0 后面那个数字就表示打开的伪终端序号,你可以尝试再打开一个终端,然后在里面输入 who am i ,看第二列是不是就变成 pts/1 了,第三列则表示当前伪终端的启动时间。

who 命令其它常用参数

                                                                      
   

参数

   
   

说明

   
   

-a

   
   

打印能打印的全部

   
   

-d

   
   

打印死掉的进程

   
   

-m

   
   

同am i,mom likes

   
   

-q

   
   

打印当前登录用户数及用户名

   
   

-u

   
   

打印当前登录用户登录信息

   
   

-r

   
   

打印运行等级

   

2.创建用户

在 Linux 系统里, root 账户拥有整个系统至高无上的权利,比如 新建/添加 用户。

创建用户需要 root 权限,需要用到 sudo 这个命令。

使用sudo命令的两个前提

  1.   知道当前登录用户的密码
  2.   当前用户必须在 sudo 用户组

    

切换登录用户:

    

 

3.用户组

如何在Linux里面查看自己属于哪个用户组?

(1)      使用groups命令

    

每次新建用户如果不指定用户组的话,默认会自动创建一个与用户名相同的用户组;默认情况下在sudo用户组里的可以使用sudo命令获得root权限。

(2)      查看/etc/group文件

    

这里 cat 命令用于读取指定文件的内容并打印到终端输出

 | sort 表示将读取的文本进行一个字典排序再输出

使用命令过滤:

    

etc/group 文件格式说明

/etc/group 的内容包括用户组(Group)、用户组口令、GID 及该用户组所包含的用户(User),每个用户组一条记录。格式如下:

group_name:password:GID:user_list

你看到上面的 password 字段为一个 'x' 并不是说密码就是它,只是表示密码不可见而已。

将其它用户加入 sudo 用户组

默认情况下新创建的用户是不具有 root 权限的,也不在 sudo 用户组,可以让其加入sudo用户组从而获取 root 权限。

    

表明用户steve不在sudo用户组中。使用 usermod 命令可以为用户添加用户组,同样使用该命令你必需有 root 权限,你可以①直接使用 root 用户为其它用户添加用户组,或者②用其它已经在 sudo 用户组的用户使用 sudo 命令获取权限来执行该命令。

    

 

4.删除用户

    

 

二、Linux 文件权限

 

1.查看文件权限

ls 命令(不带参数):列出并显示当前目录下的文件

带参数?查看文件权限——

ls –l:使用较长格式列出文件

    

其中各项含义:【图片来自实验楼】     

    

 

文件类型

Linux 里面一切皆文件,正因为这一点才有了设备文件( /dev 目录下有各种设备文件,大都跟具体的硬件设备相关)这一说,还有 socket(网络套接字),和 pipe (管道)。

链接文件是分为两种的,软连接和硬连接,硬链接不常用,而软链接等同于 Windows 上的快捷方式。

文件权限

读权限,表示你可以使用 cat <file name> 之类的命令来读取某个文件的内容;写权限,表示你可以编辑和修改某个文件; 执行权限,通常指可以运行的二进制程序文件或者脚本文件,如同 Windows 上的 'exe' 后缀的文件,不过 Linux 上不是通过文件后缀名来区分文件的类型。你需要注意的一点是,一个目录要同时具有读权限和执行权限才可以打开,而一个目录要有写权限才允许在其中创建其它文件,这是因为目录文件实际保存着该目录里面的文件的列表等信息;所有者权限,是指你所在的用户组中的所有其它用户对于该文件的权限。

链接数

链接到该文件所在的 inode 结点的文件名数目

文件大小

以 inode 结点大小为单位来表示的文件大小,你可以给 ls 加上 -lh 参数来更直观的查看文件的大小。

 

关于 ls 命令的一些其它常用的用法:

l    ls -A

显示除了 '.'(当前目录),'..' 上一级目录之外的所有包含隐藏文件(Linux 下以 '.' 开头的文件为隐藏文件)

    

l    ls –Al

同时使用 '-A' 和 '-l' 参数:

    

l    ls -dl <目录名>

查看某一个目录的完整属性,而不是显示目录里面的文件属性

    

l    ls -AsSh

显示所有文件大小,并以普通人类能看懂的方式呈现:

其中小 s 为显示文件大小,大 S 为按文件大小排序,若需要知道如何按其它方式排序,请使用“man”命令查询。

    


 
2.变更文件所有者

先在用户steve下建立一个文件tony

    

然后切换到shiyanlou用户:

    

执行指令,将tony文件所有者变更为shiyanlou。然后用ll指令查看。

 

 3.修改文件权限

(1)二进制数字表示

    

每个文件的三组权限,分别为:拥有者,所属用户组,其他用户,这就对应这一个 "rwx",也就是一个 '7' ,所以如果我要将文件“iphone6”的权限改为只有我自己可以用那么就这样:

      

??dquote是什么?

我用Ctrl + C   退出了它

 

(2)加减赋值操作

     'g''o'还有'u',分别表示group,others,user,'+','-' 就分别表示增加和去掉相应的权限。

 
  

 

第四节Linux 目录结构及文件基本操作

1、Linux 的文件组织目录结构。

2、相对路径和绝对路径。

3、对文件的移动、复制、重命名、编辑等操作。

 

一、Linux 目录结构

Linux 是以树形目录结构的形式来构建整个系统的,可以理解为一个用户可操作系统的骨架。从逻辑上来说 Linux 的磁盘是“挂在”(挂载在)目录上的,每一个目录不仅能使用本地磁盘分区的文件系统,也可以使用网络上的文件系统。

1.FHS 标准

FHS(英文:Filesystem Hierarchy Standard 中文:文件系统层次结构标准),定义了系统中每个区域的用途、所需要的最小构成的文件和目录同时还给出了例外处理与矛盾处理。

FHS 定义了两层规范:

第一层, / 下面的各个目录应该要放什么文件数据,例如 /etc 应该要放置设置文件,/bin 与 /sbin 则应该要放置可执行文件等等。

第二层,针对 /usr 及 /var 这两个目录的子目录来定义。例如 /var/log 放置系统登录文件、/usr/share 放置共享数据等等。

输入tree / 后,运行出一大堆……

    

截一部分图示意。

FHS 依据文件系统使用的频繁与否以及是否允许用户随意改动,将目录定义为四种交互作用的形态,如下表所示:

    

2.目录路径

(1)路径

使用 cd 命令可以切换目录,在 Linux 里面使用 . 表示当前目录,.. 表示上一级目录(以. 开头的文件都是隐藏文件,所以这两个目录必然也是隐藏的,你可以使用 ls -a 命令查看隐藏文件), - 表示上一次所在目录,~通常表示当前用户的"home"目录。使用 pwd 命令可以获取当前所在路径(绝对路径)。

$ cd ..

——进入上一级目录:

$ cd ~  或者 cd /home/<你的用户名>

——进入你的“home”目录:

$ pwd

——使用 pwd 获取当前路径:

    

 

l    绝对路径

关于绝对路径,简单地说就是以根"/"目录为起点的完整路径,以你所要到的目录为终点,表现形式如: /usr/local/bin,表示根目录下的 usr 目录中的 local 目录中的 bin 目录。

l    相对路径

相对路径,也就是相对于你当前的目录的路径,相对路径是以当前目录 . 为起点,以你所要到的目录为终点,表现形式如:usr/local/bin (这里假设你当前目录为根目录)。

表示相对路径实际没有加上表示当前目录的那个 . ,而是直接以目录名开头,因为这个 usr 目录为 / 目录下的子目录,是可以省略这个 . ;如果是当前目录的上一级目录,则需要使用 ..

比如你当前目录为“home”目录,根目录就应该表示为 ../../ ,表示上一级目录("home"目录)的上一级目录("/"目录)。

下面我们以你的"home"目录为起点,分别以绝对路径和相对路径的方式进入 /usr/local/bin 目录:

# 绝对路径

$ cd /usr/local/bin

    

# 相对路径

$ cd ../../usr/local/bin

    

 

提示:在进行目录切换的过程中请多使用 Tab 键自动补全,可避免输入错误,连续按两次Tab可以显示全部候选结果

 

二、Linux 文件的基本操作

1.新建

新建空白文件

使用 touch 命令创建空白文件。

A. touch命令主要用来更改已有文件的时间戳,比如最近访问时间,最近修改时间

B. 但touch命令其在不加任何参数的情况下,只指定一个文件名,则可以创建一个为指定文件名的空白文件,并且不会覆盖已有同名文件,也可以同时指定该文件的时间戳。

 

l  创建名为 test 的空白文件:

    

l  新建目录

(1).使用 mkdir(make directories)命令可以创建一个空目录,也可同时指定创建目录的权限属性

创建名为"mydir"的空目录:

    

 

(2).使用 -p 参数,同时创建父目录(如果不存在该父目录):

    

后面的目录路径,以绝对路径的方式表示也是可以的。

 

2.复制

l  复制文件

使用cp(copy)命令复制一个文件或目录到指定目录。将之前创建的"test"文件复制到"/home/shiyanlou/father/son/grandson"目录中:

    

l  复制目录

如果直接使用cp命令,复制一个目录的话,会出现如下错误:

    

要成功复制目录需要加上-r或者-R参数,表示递归复制,就是说有点“株连九族”的意思:

    

 

3.删除

l  删除文件

使用rm(remove files or directories)命令,删除一个文件或目录:

$ rm test

     有时候你会遇到想要删除一些为只读权限的文件,直接使用rm删除会显示一个提示,你如果想忽略这提示,直接删除文件,可以使用-f参数强制删除:

$ rm -f test

    

 

l  删除目录

跟复制目录一样,要删除一个目录,也需要加上-r或-R参数:

$ rm -r family

    

 

4.移动文件与文件重命名

l  移动文件

使用mv(move or   rename files)命令,移动文件(剪切)。将文件"file1"移动到"Documents"目录mv 源目录文件 目的目录:

$ mv file1 Documents

    

l  重命名文件

将文件"file1"重命名为"myfile" mv 旧的文件名 新的文件名:

$ mv file1 myfile

    

l  批量重命名

# 使用通配符批量创建 5 个文件

$ touch file{1..5}.txt

# 批量将这 5 个后缀为 .txt 的文本文件重命名为以 .c 为后缀的文件

$ rename 's/\.txt/\.c/' *.txt

    

# 批量将这 5 个文件,文件名改为大写

$ rename 'y/a-z/A-Z/' *.c

    

rename是先使用第二个参数的通配符匹配所有后缀为.txt的文件,然后使用第一个参数提供的正则表达式将匹配的这些文件的.txt后缀替换为.c

 

5.查看文件

使用cat,tac和nl命令查看文件

这两个命令都是用来打印文件内容到标准输出(终端),其中cat为正序显示,tac倒序显示

标准输入输出:当我们执行一个 shell 命令行时通常会自动打开三个标准文件,即标准输入文件(stdin),默认对应终端的键盘;标准输出文件(stdout)和标准错误输出文件(stderr),这两个文件都对应被重定向到终端的屏幕,以便我们能直接看到输出内容。进程将从标准输入文件中得到输入数据,将正常输出数据输出到标准输出文件,而将错误信息送到标准错误文件中。

比如我们要查看之前从"/etc"目录下拷贝来的passwd文件:

$ cat passwd

    

可以加上-n参数显示行号:

$ cat -n passwd

    

 

nl命令——添加行号并打印,这是个比cat -n更专业的行号打印命令。

这里简单列举它的常用的几个参数:

-b : 指定添加行号的方式,主要有两种:

    -b a:表示无论是否为空行,同样列出行号("cat -n"就是这种方式)

    -b t:只列出非空行的编号并列出(默认为这种方式)

-n : 设置行号的样式,主要有三种:

    -n ln:在行号字段最左端显示

    -n rn:在行号字段最右边显示,且不加 0

    -n rz:在行号字段最右边显示,且加 0

-w : 行号字段占用的位数(默认为 6 位)

 

使用moreless命令分页查看文件

more命令比较简单,只能向一个方向滚动

less为基于"more"和"vi"开发,功能更强大。

less 的使用基本和 more 一致,具体使用请查看 man 手册。

使用more工具打开passwd文件:

$ more passwd

      

    

打开后默认只显示一屏内容,终端底部显示当前阅读的进度(百分比)。可以使用Enter键向下滚动一行,使用Space键向下滚动一屏,按下h显示帮助,q退出。

使用head和tail命令查看文件

这两个命令那些性子比较急的人应该会比较喜欢,因为它们一个是只查看的头几行(默认为10行,不足10行则显示全部)和尾几行。还是拿 passwd 文件举例,比如当我们想要查看最近新增加的用户,那么我们可以查看这个/etc/passwd文件,不过我们前面也看到了,这个文件里面一大堆乱糟糟的东西,看起来实在费神啊。这里想到系统新增加一个用户,应该会将用户的信息添加到passwd文件的最后,那么这时候我们就可以使用tail命令了:

$ tail /etc/passwd

    

甚至更直接的只看一行, 加上-n参数,后面紧跟行数:

$ tail -n 1 /etc/passwd

      

 

tail -f,可以实现不停地读取某个文件的内容并显示,这可让我们动态查看日志起到实时监视的作用。

 

6.查看文件类型

前面我提到过,在 Linux 下面文件的类型不是根据文件后缀来判断的,我们通常使用file命令可以查看文件的类型:

$ file /bin/ls

    

这表示这是一个可执行文件,运行在 64 位平台,并使用了动态链接文件(共享库)。

 

7.编辑文件

$ vimtutor

    

 

 

第五节 环境变量与文件查找

A.环境变量的作用与用法

B.几种搜索文件的方法

 

一、环境变量

1.变量

Shell 变量是计算机中用于记录一个值,字符或字符串的符号

通常变量与值是一对一的关系,可以通过表达式读取它的值赋值给其它变量,也可以直接指定数值赋值给任意变量。

变量的作用域即变量的有效范围

 

l  在 Shell 中创建一个变量:

——使用declare命令创建一个变量名为 tmp 的变量:

$ declare tmp

其实也可以不用 declare 预声明一个变量,直接即用即创建

declare在创建其它指定类型的变量(如数组)时会用到。

l  给变量赋值:

——使用=号赋值运算符为变量 tmp 赋值为 shiyanlou:

$ tmp=shiyanlou

l  读取变量的值,

——使用echo命令和$符号($符号用于表示引用一个变量的值):

$ echo $tmp

      

※变量名只能是英文字母,数字或者下划线,且不能以数字作为开头。

 

2.环境变量

环境变量就是作用域比自定义变量要大,(Shell 的环境变量作用于自身和它的子进程)

通常我们会涉及到的环境变量有三种

•     当前 Shell 进程私有用户自定义变量,如上面我们创建的 temp 变量,只在当前 Shell 中有效。                                                     

•     Shell 本身内建的变量。                                            

•     从自定义变量导出的环境变量。                                      

也有三个与上述三种环境变量相关的命令,setenvexport

  1.   set    显示当前 Shell 所有环境变量,包括其内建环境变量(与 Shell 外观等相关),用户自定义变量及导出的环境变量
  2.   env   显示与当前用户相关的环境变量,还可以让命令在指定环境中运行
  3.   export   显示从 Shell 中导出成环境变量的变量,也能通过它将自定义变量导出为环境变量

 

使用vimdiff工具比较一下它们之间的差别:

$ temp=shiyanlou

$ export temp_env=shiyanlou

$ env|sort>env.txt

$ export|sort>export.txt

$ set|sort>set.txt

    

上述操作将命令输出通过管道|使用sort命令排序,再重定向到对象文本文件中

$ vimdiff env.txt export.txt set.txt

使用vimdiff工具比较导出的几个文件的内容。

    

环境变量,可以简单的理解成在当前进程的子进程是否有效,有效则为环境变量,否则不是。

我们这里用export命令来体会一下,先在 Shell 中设置一个变量temp=shiyanlou,然后再新创建一个子 Shell 查看temp变量的值:

    

      

 

※为了与普通变量区分,通常我们习惯将环境变量名设为大写

 

3.命令的查找路径与顺序

Shell通过环境变量PATH来进行搜索查找命令,PATH里面保存了Shell中执行的命令的搜索路径。

查看PATH环境变量的内容:

$ echo $PATH

    

通常这一类目录下放的都是可执行文件,当我们在 Shell 中执行一个命令时,系统就会按照 PATH 中设定的路径按照顺序依次到目录中去查找,如果存在同名的命令,则执行先找到的那个

 

l  创建一个最简单的可执行 Shell 脚本和一个使用 C 语言创建的"hello world"程序

1)          创建一个 Shell 脚本文件:

$ vim hello_shell.sh

2)          在脚本中添加如下内容,保存并退出(注意不要省掉第一行,这不是注释,论坛有用户反应会有语法错误,就是因为没有了第一行):

#!/bin/zsh

for ((i=0; i<10; i++));do

    echo "hello shell"

done

exit 0

???怎么退出bash啊!!!

3)          为文件添加可执行权限:

$ chmod 755 hello_shell.sh

4)          执行脚本

$ ./hello_shell.sh

5)          创建一个 C 语言"hello world"程序:

$ vim hello_world.c

#include <stdio.h>

int main(void)

{

    printf("hello   world!\n");

    return 0;

}

6)          使用 gcc 生成可执行文件:

$ gcc -o hello_world hello_world.c

gcc 生成二进制文件默认具有可执行权限,不需要修改

7)          在 shiyanlou 家目录创建一个mybin目录,并将上述 hello_shell.sh   和 hello_world 文件移动到其中:

$ mkdir mybin

$ mv hello_shell.sh hello_world mybin/

8)          现在在mybin目录中分别运行你刚刚创建的两个程序:

$ cd mybin

$ ./hello_shell.sh

$ ./hello_world

 

回到上一级目录,也就是shiyanlou家目录,当再想运行那两个程序时,会发现提示命令找不到,除非加上命令的完整路径,但那样很不方便,如何做到想使用系统命令一样执行自己创建的脚本文件或者程序呢?那就要将命令所在路径添加到PATH环境变量了。

 

4.添加自定义路径到“PATH”环境变量

在前面我们应该注意到PATH里面的路径是以:作为分割符,所以我们可以这样添加自定义路径:

$ PATH=$PATH:/home/shiyanlou/mybin

注意这里一定要使用绝对路径

 

有没有方法让添加的环境变量全局有效?或者每次启动 Shell 时自动执行上面添加自定义路径到 PATH 的命令?——让它自动执行

在每个用户的 home 目录中有一个 Shell 每次启动时会默认执行一个配置脚本,以初始化环境,包括添加一些用户自定义环境变量等等。zsh 的配置文件是.zshrc,相应 Bash 的配置文件为.bashrc。它们在etc下还都有一个或多个全局的配置文件,不过我们一般只修改用户目录下的配置文件。

我们可以简单的使用下面命令直接添加内容到.zshrc中:

$ echo "PATH=$PATH:/home/shiyanlou/mybin" >> .zshrc

上述命令中>>表示将标准输出以追加的方式重定向到一个文件中,注意前面用到的>是以覆盖的方式重定向到一个文件中,使用的时候一定要注意分辨。在指定文件不存在的情况下都会创建新的文件。

 

5.修改和删除已有变量

l  变量修改

变量的修改有以下几种方式:

${变量名#匹配字串}    从头向后开始匹配,删除符合匹配字串的最短数据

${变量名##匹配字串}  从头向后开始匹配,删除符合匹配字串的最长数据

${变量名%匹配字串}   从尾向前开始匹配,删除符合匹配字串的最短数据

${变量名%%匹配字串}  从尾向前开始匹配,删除符合匹配字串的最长数据

${变量名/旧的字串/新的字串} 将符合旧字串的第一个字串替换为新的字串

${变量名//旧的字串/新的字串}    将符合旧字串的全部字串替换为新的字串

 

比如要修改我们前面添加到 PATH 的环境变量。为了避免操作失误导致命令找不到,我们先将 PATH 赋值给一个新的自定义变量 path:

$ path=$PATH

$ echo $path

$ path=${path%/home/shiyanlou/mybin}

# 或使用通配符,*表示任意多个任意字符

$ path=${path%*/mybin}

    

 

l  变量删除

可以使用unset命令删除一个环境变量:

$ unset temp

 

6.如何让环境变量立即生效

使用source命令来让其立即生效:

$ source .zshrc

source命令还有一个别名就是 . ,注意与表示当前路径的那个点区分开,虽然形式一样,但作用和使用方式一样,上面的命令如果替换成.的方式就该是

$ . ./.zshrc

注意第一个点后面有一个空格,而且后面的文件必须指定完整的绝对或相对路径名,source 则不需要。

 

二、搜索文件

与搜索相关的命令常用的有如下几个whereis which find locate

whereis简单快速

$whereis who

    

它找到了三个路径,两个可执行文件路径和一个 man 在线帮助文件所在路径。这个搜索很快,因为它并没有从硬盘中依次查找,而是直接从数据库中查询

whereis只能搜索二进制文件(-b)man帮助文件(-m)和源代码文件(-s)。如果想要获得更全面的搜索结果可以使用locate命令。

 

locate快而全

Locate命令是通过"/var/lib/mlocate/mlocate.db"数据库查找,系统会使用定时任务每天自动执行updatedb命令更新这个数据库一次,所以有时候你刚添加的文件,它可能会找不到,需要手动执行一次updatedb命令(。

可以用来查找指定目录下的不同文件类型,如查找 /etc 下所有以 sh 开头的文件:

$ locate /etc/sh

    

注意,它不只是在 etc 目录下查找并会自动递归子目录进行查找

查找 /usr/share/ 下所有 jpg 文件:

$ locate /usr/share/\*.jpg

    

注意要添加*号前面的反斜杠转义,否则会无法找到

只统计数目:-c参数,

忽略大小写进行查找:-i参数

whereis 的-b,-m,-s同样可以使用。

 

which小而精

which本身是 Shell 内建的一个命令,我们通常使用which来确定是否安装了某个指定的软件,因为它只从PATH环境变量指定的路径中去搜索命令

$ which man

    

 

find精而细

find应该是这几个命令中最强大的了,它不但可以通过文件类型、文件名进行查找而且可以根据文件的属性(如文件的时间戳,文件的权限等)进行搜索。

1)          在指定目录下搜索指定文件名的文件:

$ find /etc/ -name interfaces

    

注意 find 命令的路径是作为第一个参数的,基本命令格式为 find [path]   [option] [action]

2)          与时间相关的命令参数:

-atime  最后访问时间

-ctime   创建时间

-mtime 最后修改时间

 

以-mtime参数为例:

•     -mtime n: n 为数字,表示为在n天之前的”一天之内“修改过的文件

•     -mtime +n: 列出在n天之前(不包含n天本身)被修改过的文件

•     -mtime -n: 列出在n天之前(包含n天本身)被修改过的文件

•     newer file: file为一个已存在的文件,列出比file还要新的文件名

 

列出 home 目录中,当天(24 小时之内)有改动的文件:

$ find ~ -mtime 0

    

列出用户家目录下比Code文件夹新的文件:

$ find ~ -newer /home/shiyanlou/Code

    

 

 

第六节 文件打包与压缩

Linux 上常用的 压缩/解压 工具,介绍了 zip,rar,tar 的使用。

 

一、文件打包和解压缩

 

Linux压缩文件格式简介:

*.zip  zip程序打包压缩的文件

*.rar  rar程序压缩的文件

*.7z   7zip程序压缩的文件

*.tar  tar程序打包,未压缩的文件

*.gz   gzip程序(GNU   zip)压缩的文件

*.xz   xz程序压缩的文件

*.bz2  bzip2程序压缩的文件

*.tar.gz   tar打包,gzip程序压缩的文件

*.tar.xz   tar打包,xz程序压缩的文件

*tar.bz2   tar打包,bzip2程序压缩的文件

*.tar.7z   tar打包,7z程序压缩的文件

 

1.zip压缩打包程序

 

使用zip打包文件夹:

$   zip -r -q -o shiyanlou.zip /home/shiyanlou

$ du   -h shiyanlou.zip

$   file shiyanlou.zip

    

上面命令将 shiyanlou 的 home 目录打包成一个文件,并查看了打包后文件的大小和类型。

-r,表示递归打包包含子目录的全部内容

-q,表示为安静模式,即不向屏幕输出信息

-o,表示输出文件,需在其后紧跟打包输出文件名

du,查看打包后文件的大小

 

l  设置压缩级别为9和1(9最大,1最小),重新打包:

$ zip -r -9 -q -o shiyanlou_9.zip /home/shiyanlou -x ~/*.zip

$ zip -r -1 -q -o shiyanlou_1.zip /home/shiyanlou -x ~/*.zip

这里添加了一个参数用于设置压缩级别-[1-9],1表示最快压缩但体积大,9表示体积最小但耗时最久。最后那个-x是为了排除我们上一次创建的 zip 文件,否则又会被打包进这一次的压缩文件中。默认压缩级别应该是最高的。

注意:这里只能使用绝对路径

我们再用du命令分别查看默认压缩级别、最低、最高压缩级别及未压缩的文件的大小:

$ du -h -d 0 *.zip ~ | sort

    

通过man 手册可知:

h, --human-readable(顾名思义,你可以试试不加的情况)

d, --max-depth(所查看文件的深度)

 

l  创建加密zip包

使用-e参数可以创建加密压缩包:

$   zip -r -e -o shiyanlou_encryption.zip /home/shiyanlou

    

注意: 关于zip命令,因为 Windows 系统与 Linux/Unix 在文本文件格式上的一些兼容问题,比如换行符(为不可见字符),在 Windows 为 CR+LF(Carriage-Return+Line-Feed:回车加换行),而在 Linux/Unix 上为 LF(换行),所以如果在不加处理的情况下,在 Linux 上编辑的文本,在 Windows 系统上打开可能看起来是没有换行的。如果你想让你在 Linux 创建的 zip 压缩文件在 Windows 上解压后没有任何问题,那么你还需要对命令做一些修改:

$ zip -r -l -o shiyanlou.zip   /home/shiyanlou

需要加上-l参数将LF转换为CR+LF来达到以上目的。

 

2.使用unzip命令解压缩zip文件

l  将shiyanlou.zip解压到当前目录:

$   unzip shiyanlou.zip

 

l  使用安静模式,将文件解压到指定目录

$   unzip -q shiyanlou.zip -d ziptest

    

上述指定目录不存在,将会自动创建。

l  不解压只想查看压缩包的内容:-l参数:

$   unzip -l shiyanlou.zip

 

注意:使用unzip解压文件时我们同样应该注意兼容问题,不过这里我们关心的不再是上面的问题,而是中文编码的问题,通常 Windows 系统上面创建的压缩文件,如果有有包含中文的文档或以中文作为文件名的文件时默认会采用 GBK 或其它编码,而 Linux 上面默认使用的是 UTF-8 编码,如果不加任何处理,直接解压的话可能会出现中文乱码的问题(有时候它会自动帮你处理),为了解决这个问题,我们可以在解压时指定编码类型。

使用-O(英文字母,大写o)参数指定编码类型:

unzip   -O GBK 中文压缩文件.zip

 

3.rar打包压缩命令

rar也是 Windows 上常用的一种压缩文件格式,在 Linux 上可以使用rar和unrar工具分别创建和解压 rar 压缩包。

 

l  安装rar和unrar工具:

$   sudo apt-get update

$   sudo apt-get install rar unrar

l  从指定文件或目录创建压缩包或添加文件到压缩包:

$ rm   *.zip

$   rar a shiyanlou.rar .

    

上面的命令使用a参数添加一个目录~到一个归档文件中,如果该文件不存在就会自动创建。

注意:rar 的命令参数没有-,如果加上会报错。

l  从指定压缩包文件中删除某个文件:

$   rar d shiyanlou.rar .zshrc

    

l  查看不解压文件:

$   rar l shiyanlou.rar

    

l  使用unrar解压rar文件

全路径解压:

$   unrar x shiyanlou.rar

    

去掉路径解压:

$ mkdir tmp

$ unrar e shiyanlou.rar tmp/

    

rar命令参数非常多,上面只涉及了一些基本操作

 

4.tar打包工具

 

在 Linux 上面更常用的是tar工具,tar 原本只是一个打包工具,只是同时还是实现了对 7z,gzip,xz,bzip2 等工具的支持,这些压缩工具本身只能实现对文件或目录(单独压缩目录中的文件)的压缩,没有实现对文件的打包压缩,所以我们也无需再单独去学习其他几个工具,tar 的解压和压缩都是同一个命令,只需参数不同,使用比较方便。

 

下面先掌握tar命令一些基本的使用方式,即不进行压缩只是进行打包(创建归档文件)和解包的操作。

 

l  创建一个 tar 包:

$   tar -cf shiyanlou.tar ~

    

    

上面命令中:

-c表示创建一个 tar 包文件

-f用于指定创建的文件名,注意文件名必须紧跟在-f参数之后,比如不能写成tar -fc   shiyanlou.tar,可以写成tar -f shiyanlou.tar -c   ~。

-v参数以可视的的方式输出打包的文件

上面会自动去掉表示绝对路径的/,你也可以使用-P保留绝对路径符。

 

l  解包一个文件(-x参数)到指定路径的已存在目录(-C参数):

$   mkdir tardir

$   tar -xf shiyanlou.tar -C tardir

    

l  只查看不解包文件-t参数:

$   tar -tf shiyanlou.tar

 

l  保留文件属性和跟随链接(符号链接或软链接),有时候我们使用tar备份文件当你在其他主机还原时希望保留文件的属性(-p参数)和备份链接指向的源文件而不是链接本身(-h参数):

$   tar -cphf etc.tar /etc

 

对于创建不同的压缩格式的文件,对于tar来说是相当简单的,需要的只是换一个参数,这里我们就以使用gzip工具创建*.tar.gz文件为例来说明。

我们只需要在创建 tar 文件的基础上添加-z参数,使用gzip来压缩文件:

$   tar -czf shiyanlou.tar.gz ~

    

解压*.tar.gz文件:

$   tar -xzf shiyanlou.tar.gz

现在我们要使用其他的压缩工具创建或解压相应文件只需要更改一个参数即可:

*.tar.gz    -z

*.tar.xz     -J

*tar.bz2   -j

 

 

第七节 文件系统操作与磁盘管理

 

一、简单文件系统操作

 

1.查看磁盘和目录的容量

l  使用 df 命令查看磁盘的容量

$ df

    

一般使用情况下,我们更多只是关心第一行的内容也就是环境中的rootfs或者物理主机上的/dev/sda2

 

"rootfs" : (Root File   System)它是 Ramfs(Ramfs 是一个非常简单的 Linux 文件系统用于实现磁盘缓存机制作为动态可调整大小的基于 ram 的文件系统)或者 tmpfs 的一个特殊实例,它作为系统启动时内核载入内存之后,在挂载真正的的磁盘之前的一个临时文件系统。通常的主机会在系统启动后用磁盘上的文件系统替换,只是在一些嵌入式系统中会只存在一个 rootfs ,或者像我们目前遇到的情况运行在虚拟环境中共享主机资源的系统也可能会采用这种方式。

物理主机上的 /dev/sda2 是对应着主机硬盘的分区,后面的数字表示分区号,数字前面的字母 a 表示第几块硬盘(也可能是可移动磁盘),你如果主机上有多块硬盘则可能还会出现 /dev/sdb,/dev/sdc 这些磁盘设备都会在 /dev 目录下以文件的存在形式。

 

$ df   -h

    

 

l  使用 du 命令查看目录的容量

# 默认同样以 blocks 的大小展示

$ du

# 加上`-h`参数,以更易读的方式展示

$ du   -h

-d参数指定查看目录的深度

# 只查看1级目录的信息

$ du   -h -d 0 ~

# 查看2级

$ du   -h -d 1 ~

    

 

二、简单的磁盘管理

 

1.创建虚拟磁盘

 

l  dd 命令简介(部分说明来自dd (Unix) wiki))

dd命令用于转换和复制文件,不过它的复制不同于cp。之前提到过关于 Linux 的很重要的一点,一切即文件,在 Linux 上,硬件的设备驱动(如硬盘)和特殊设备文件(如/dev/zero和/dev/random)都像普通文件一样,只要在各自的驱动程序中实现了对应的功能,dd 也可以读取自和/或写入到这些文件。这样,dd也可以用在备份硬件的引导扇区、获取一定数量的随机数据或者空数据等任务中。dd程序也可以在复制时处理数据,例如转换字节序、或在 ASCII 与 EBCDIC 编码间互换

dd的命令行语句与其他的 Linux 程序不同,因为它的命令行选项格式为选项=值,而不是更标准的--选项 值或-选项=值。dd默认从标准输入中读取,并写入到标准输出中,但可以用选项if(input file,输入文件)和of(output file,输出文件)改变。

我们先来试试用dd命令从标准输入读入用户输入到标准输出或者一个文件:

 

# 输出到文件

$ dd   of=test bs=10 count=1 # 或者 dd if=/dev/stdin of=test   bs=10 count=1

# 输出到标准输出

$ dd   if=/dev/stdin of=/dev/stdout bs=10 count=1

 

 

上述命令从标准输入设备读入用户输入(缺省值,所以可省略)然后输出到 test 文件,bs(block size)用于指定块大小(缺省单位为 Byte,也可为其指定如'K','M','G'等单位),count用于指定块数量。如上图所示,我指定只读取总共 10 个字节的数据,当我输入了“hello shiyanlou”之后加上空格回车总共 16 个字节(一个英文字符占一个字节)内容,显然超过了设定大小。使用和du和cat命令看到的写入完成文件实际内容确实只有 10 个字节(那个黑底百分号表示这里没有换行符),而其他的多余输入将被截取并保留在标准输入。

 

前面说到dd在拷贝的同时还可以实现数据转换,那下面就举一个简单的例子:将输出的英文字符转换为大写再写入文件

$ dd   if=/dev/stdin of=test bs=10 count=1 conv=ucase

 

l  使用 dd 命令创建虚拟镜像文件

 

1)          从/dev/zero设备创建一个容量为 256M 的空文件:

$ dd   if=/dev/zero of=virtual.img bs=1M count=256

$ du   -h virtual.img

    

 

2)          然后我们要将这个文件格式化(写入文件系统),这里我们要学到一个(准确的说是一组)新的命令来完成这个需求。

 

使用 mkfs 命令格式化磁盘(我们这里是自己创建的虚拟磁盘镜像)

 

在命令行输入 mkfs 然后按下Tab键,可以看到很多个以 mkfs 为前缀的命令,这些不同的后缀其实就是表示着不同的文件系统,可以用 mkfs 格式化成的文件系统:

    

 

我们可以简单的使用下面的命令来将我们的虚拟磁盘镜像格式化为ext4文件系统:

$   mkfs.ext4 virtual.img

    

可以看到实际 mkfs.ext4 是使用 mke2fs 来完成格式化工作的。

l  使用 mount 命令挂载磁盘到目录树

用户在 Linux/UNIX 的机器上打开一个文件以前,包含该文件的文件系统必须先进行挂载的动作,此时用户要对该文件系统执行 mount 的指令以进行挂载。通常是使用在 USB 或其他可移除存储设备上,而根目录则需要始终保持挂载的状态。又因为 Linux/UNIX 文件系统可以对应一个文件而不一定要是硬件设备,所以可以挂载一个包含文件系统的文件到目录树。

Linux/UNIX 命令行的 mount 指令是告诉操作系统,对应的文件系统已经准备好,可以使用了,而该文件系统会对应到一个特定的点(称为挂载点)。挂载好的文件、目录、设备以及特殊文件即可提供用户使用。

我们先来使用mount来查看下主机已经挂载的文件系统:

$   sudo mount

    

输出的结果中每一行表示一个设备或虚拟设备,每一行最前面是设备名,然后是 on 后面是挂载点,type 后面表示文件系统类型,再后面是挂载选项(比如可以在挂载时设定以只读方式挂载等等)。

mount命令的一般格式如下:

mount [options]   [source] [directory]

 

一些常用操作:

mount [-o [操作选项]] [-t 文件系统类型] [-w|--rw|--ro] [文件系统源] [挂载点]

 

我们现在直接来挂载我们创建的虚拟磁盘镜像到/mnt目录:

$   mount -o loop -t ext4 virtual.img /mnt  

# 也可以省略挂载类型,很多时候 mount 会自动识别

 

# 以只读方式挂载

$   mount -o loop --ro virtual.img /mnt

# 或者mount   -o loop,ro virtual.img /mnt

 

l  使用 umount 命令卸载已挂载磁盘

# 命令格式   sudo umount 已挂载设备名或者挂载点,如:

$   sudo umount /mnt

不过遗憾的是,由于我们环境的问题(环境中使用的 Linux 内核在编译时没有添加对 Loop device的支持),所以你将无法挂载成功:!!!!!!!!!!!伤害我感情!!!!!!

 

l  如何为磁盘分区。

 

# 查看硬盘分区表信息

$   sudo fdisk -l

 

 

输出结果中开头显示了主机上的磁盘的一些信息,包括容量扇区数,扇区大小,I/O 大小等信息。

 

我们重点开一下中间的分区信息,/dev/sda1,/dev/sda2 为主分区分别安装了 Windows 和 Linux 操作系统,/dev/sda3 为交换分区(可以理解为虚拟内存),/dev/sda4 为扩展分区其中包含 /dev/sda5,/dev/sda6,/dev/sda7,/dev/sda8 四个逻辑分区,因为主机上有几个分区之间有空隙,没有对齐边界扇区,所以分区之间的不是完全连续的。

 

# 进入磁盘分区模式

$   sudo fdisk virtual.img

 

 

l  使用 losetup 命令建立镜像与回环设备的关联

$   sudo losetup /dev/loop0 virtual.img

# 如果提示设备忙你也可以使用其它的回环设备,"ls /dev/loop*"参看所有回环设备

 

# 解除设备关联

$   sudo losetup -d /dev/loop0

然后再使用mkfs格式化各分区(前面我们是格式化整个虚拟磁盘镜像文件或磁盘),不过格式化之前,我们还要为各分区建立虚拟设备的映射,用到kpartx工具,需要先安装:

$   sudo apt-get install kpartx

$   sudo kpart kpartx -av /dev/loop0

 

# 取消映射

$   sudo kpart kpartx -dv /dev/loop0

 

接着再是格式化,将其全部格式化为 ext4:

$   sudo mkfs.ext4 -q /dev/mapper/loop0p1

$   sudo mkfs.ext4 -q /dev/mapper/loop0p5

$   sudo mkfs.ext4 -q /dev/mapper/loop0p6

 

格式化完成后在/media目录下新建四个空目录用于挂载虚拟磁盘:

$   mkdir -p /media/virtualdisk_{1..3}

# 挂载磁盘分区

$   sudo mount /dev/mapper/loop0p1 /media/virtualdisk_1

$   sudo mount /dev/mapper/loop0p5 /media/virtualdisk_2

$   sudo mount /dev/mapper/loop0p6 /media/virtualdisk_3

 

# 卸载磁盘分区

$   sudo umount /dev/mapper/loop0p1

$   sudo umount /dev/mapper/loop0p5

$   sudo umount /dev/mapper/loop0p6

 

然后:

$ df   -h

 

 

第八节 命令执行顺序控制与管道

顺序执行、选择执行、管道、cut 命令、grep 命令、wc 命令、sort 命令等,高效率使用 Linux 的技巧。

 

一、命令执行顺序的控制

1.顺序执行多条命令

$   sudo apt-get update

# 等待——————————然后输入下面的命令

$   sudo apt-get install some-tool

# 等待——————————然后输入下面的命令

$   some-tool

 

简单的顺序执行你可以使用;来完成,比如上述操作你可以:

 

$   sudo apt-get update;sudo apt-get install some-tool;some-tool

# 让它自己运行

 

2.有选择的执行命令

使用which来查找是否安装某个命令,如果找到就执行该命令,否则什么也不做

$   which cowsay>/dev/null && cowsay -f head-in ohch~

如果没有安装cowsay,你可以先执行一次上述命令,你会发现什么也没发生,你再安装好之后你再执行一次上述命令,你也会发现一些惊喜。

 

&&用来实现选择性执行

它表示如果前面的命令执行结果(不是表示终端输出的内容,而是表示命令执行状态的结果)返回0则执行后面的,否则不执行,你可以从$?环境变量获取上一次命令的返回结果:

    

 

shell中的||除了也可用于表示逻辑与和或之外,就是可以实现这里的命令执行顺序的简单控制。

||在这里就是与&&相反的控制效果,当上一条命令执行结果为≠0($?0)时则执行它后面的命令:

$   which cowsay>/dev/null || echo "cowsay has not been install, please   run 'sudo apt-get install cowsay' to install"

    

 

除了上述基本的使用之外,我们还可以结合这&&和||来实现一些操作,比如:

$   which cowsay>/dev/null && echo "exist" || echo "not   exist"

    

 

 

二、管道

管道是一种通信机制,通常用于进程间的通信(也可通过socket进行网络通信),它表现出来的形式就是将前面每一个进程的输出(stdout)直接作为下一个进程的输入(stdin)。

 

管道又分为匿名管道具名管道

匿名管道,在命令行中由|分隔符表示。

具名管道简单的说就是有名字的管道,通常只会在源程序中用到具名管道。

 

1.试用

 

先试用一下管道,比如查看/etc目录下有哪些文件和目录,使用ls命令来查看:

$ ls   -al /etc

 

有太多内容,屏幕不能完全显示,这时候可以使用滚动条或快捷键滚动窗口来查看。不过这时候可以使用管道:

$ ls   -al /etc | less

通过管道将前一个命令(ls)的输出作为下一个命令(less)的输入,然后就可以一行一行地看。

 

2.cut 命令,打印每一行的某一字段

l  打印/etc/passwd文件中以:为分隔符的第1个字段和第6个字段分别表示用户名和其下目录:

$   cut /etc/passwd -d ':' -f 1,6

    

l  打印/etc/passwd文件中每一行的前N个字符:

# 前五个(包含第五个)

$ cut /etc/passwd -c -5

# 前五个之后的(包含第五个)

$ cut /etc/passwd -c 5-

# 第五个

$ cut /etc/passwd -c 5

# 2到5之间的(包含第五个)

$ cut /etc/passwd -c 2-5

 

3.grep 命令,在文本中或 stdin 中查找匹配字符串

 

grep命令的一般形式为:

grep [命令选项]... 用于匹配的表达式 [文件]...

l  搜索/home/shiyanlou目录下所有包含"shiyanlou"的所有文本文件,并显示出现在文本中的行号:

$   grep -rnI "shiyanlou" ~

    

-r 参数表示递归搜索子目录中的文件

-n表示打印匹配项行号

-I表示忽略二进制文件

 

l  在匹配字段中使用正则表达式:

# 查看环境变量中以"yanlou"结尾的字符串

$   export | grep ".*yanlou$"

    

其中$就表示一行的末尾。

 

4. wc 命令,简单小巧的计数工具

wc 命令用于统计并输出一个文件中行、单词和字节的数目

l  输出/etc/passwd文件的统计信息:

$ wc   /etc/passwd

    

l  分别只输出行数、单词数、字节数、字符数和输入文本中最长一行的字节数:

# 行数

$ wc   -l /etc/passwd

# 单词数

$ wc   -w /etc/passwd

# 字节数

$ wc   -c /etc/passwd

# 字符数

$ wc   -m /etc/passwd

# 最长行字节数

$ wc   -L /etc/passwd

    

注意:对于西文字符来说,一个字符就是一个字节,但对于中文字符一个汉字是大于2个字节的,具体数目是由字符编码决定的

 

再来结合管道来操作一下,下面统计 /etc 下面所有目录数

$ ls   -dl /etc/*/ | wc -l

    

 

5.sort 排序命令

将输入按照一定方式排序,然后再输出,它支持的排序有按字典排序,数字排序按月份排序随机排序反转排序指定特定字段进行排序等等。

l  默认为字典排序:

$   cat /etc/passswd | sort

    

l  反转排序:

$   cat /etc/passwd | sort –r

    

l  按特定字段排序:

$   cat /etc/passwd | sort -t':' -k 3

    

上面的-t参数用于指定字段的分隔符,这里是以":"作为分隔符;-k 字段号用于指定对哪一个字段进行排序。这里/etc/passwd文件的第三个字段为数字,默认情况下是一字典序排序的,如果要按照数字排序就要加上-n参数:

$   cat /etc/passwd | sort -t':' -k 3 -n

    

 

6. uniq 去重命令

uniq命令可以用于过滤或者输出重复行

 

l  过滤重复行

我们可以使用history命令查看最近执行过的命令(实际为读取${SHELL}_history文件,如我们环境中的~/.zsh_history文件),不过你可能只想查看使用了那个命令而不需要知道具体干了什么,那么你可能就会要想去掉命令后面的参数然后去掉重复的命令:

$   history | cut -c 8- | cut -d ' ' -f 1 | uniq

    

然后经过层层过滤,你会发现确是只输出了执行的命令那一列,不过去重效果好像不明显,仔细看你会发现它趋势去重了,只是不那么明显,之所以不明显是因为uniq命令只能去连续重复的行,不是全文去重,所以要达到预期效果,我们先排序

$   history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq

# 或者$   history | cut -c 8- | cut -d ' ' -f 1 | sort –u

    

 

l  输出重复行

# 输出重复过的行(重复的只输出一个)及重复次数

$   history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq –dc

    

# 输出所有重复的行

$   history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq –D

    

 

 

第九节 简单的文本处理

tr(注意不是tarcoljoinpaste

 

一、常用的文本处理命令

 

二、文本处理命令

 

1.tr 命令

tr 命令可以用来删除一段文本信息中的某些文字。或者将其进行转换。

使用方式:

tr [option]...SET1 [SET2]

常用的选项有:

-d    删除和set1匹配的字符,注意不是全词匹配也不是按字符顺序匹配

-s    去除set1指定的在输入文本中连续并重复的字符

 

操作举例:

# 删除   "hello shiyanlou" 中所有的'o','l','h'

$   echo 'hello shiyanlou' | tr -d 'olh'

# 将"hello"   中的ll,去重为一个l

$   echo 'hello' | tr -s 'l'

# 将输入文本,全部转换为大写或小写输出

$   cat /etc/passwd | tr '[:lower:]' '[:upper:]'

# 上面的'[:lower:]'   '[:upper:]'你也可以简单的写作'[a-z]' '[A-Z]',当然反过来将大写变小写也是可以的

    

 

2.col 命令

col 命令可以将Tab换成对等数量的空格建,或反转这个操作。

 

使用方式:

col [option]

常用的选项有:

-x  将Tab转换为空格

-h  将空格转换为Tab(默认选项)

 

操作举例:

# 查看   /etc/protocols 中的不可见字符,可以看到很多 ^I ,这其实就是 Tab   转义成可见字符的符号

$   cat -A /etc/protocols

    

# 使用 col   -x 将 /etc/protocols 中的 Tab 转换为空格,然后再使用 cat   查看,你发现 ^I 不见了

$   cat /etc/protocols | col -x | cat -A

    

 

3.join命令

用于将两个文件中包含相同内容的那一行合并在一起。

 

使用方式:

join [option]... file1 file2

常用的选项有:

-t  指定分隔符,默认为空格

-i  忽略大小写的差异

-1  指明第一个文件要用哪个字段来对比,,默认对比第一个字段

-2  指明第二个文件要用哪个字段来对比,,默认对比第一个字段

 

操作举例:

# 创建两个文件

$   echo '1 hello' > file1

$   echo '1 shiyanlou' > file2

$   join file1 file2

    

# 将/etc/passwd与/etc/shadow两个文件合并,指定以':'作为分隔符

$   sudo join -t':' /etc/passwd /etc/shadow

    

# 将/etc/passwd与/etc/group两个文件合并,指定以':'作为分隔符, 分别比对第4和第3个字段

$   sudo join -t':' -1 4 /etc/passwd -2 3 /etc/group

    

 

4.paste命令

    paste这个命令与join 命令类似,它是在不对比数据的情况下,简单地将多个文件合并一起,以Tab隔开。

 

使用方式:

paste [option] file...

常用的选项有:

-d  指定合并的分隔符,默认为Tab

-s  不合并到一行,每个文件为一行

 

操作举例:

$   echo hello > file1

$   echo shiyanlou > file2

$   echo www.shiyanlou.com > file3

$   paste -d ':' file1 file2 file3

$   paste -s file1 file2 file3

    

 

第十节  数据流重定向

你可能对重定向这个概念感到些许陌生,但你应该在前面的课程中多次见过>或>>操作了,并知道他们分别是将标准输出导向一个文件或追加到一个文件中。这其实就是重定向,将原本输出到标准输出的数据重定向到一个文件中,因为标准输出(/dev/stdout)本身也是一个文件,我们将命令输出导向另一个文件自然也是没有任何问题的。

 

一、数据流重定向

下面我们简单的回顾一下我们前面经常用到的两个重定向操作:

$   echo 'hello shiyanlou' > redirect

$   echo 'www.shiyanlou.com' >> redirect

$   cat redirect

    

当然前面没有用到的<和<<操作也是没有问题的,如你理解的一样,它们的区别在于重定向的方向不一致而已,>表示是从左到右,<右到左。

 

1.简单的重定向

Linux 默认提供了三个特殊设备,用于终端的显示和输出,分别为stdin(标准输入,对应于你在终端的输入),stdout(标准输出,对应于终端的输出),stderr(标准错误输出,对应于终端的输出)。

 

文件描述符 设备文件     说明

0           /dev/stdin       标准输入

1           /dev/stdout    标准输出

2           /dev/stderr     标准错误

 

文件描述符:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于 UNIX、Linux 这样的操作系统。

另外还有一个符号-,它可以同时作为前一个命令的。

 

我们可以这样使用这些文件描述符:

1)          默认使用终端的标准输入作为命令的输入和标准输出作为命令的输出

$ cat  

(按Ctrl+C退出)

 

2)          将cat的连续输出(heredoc方式)重定向到一个文件

$   mkdir Documents

$   cat > Documents/test.c\~ <<EOF

#include   <stdio.h>

 

int   main()

{

    printf("hello world\n");

    return 0;

}

 

EOF

 

3)          将一个文件作为命令的输入,标准输出作为命令的输出

$   cat Documents/test.c\~

 

4)          将echo命令通过管道传过来的数据作为cat命令的输入,将标准输出作为命令的输出

$   echo 'hi' | cat

 

5)          将echo命令的输出从默认的标准输出重定向到一个普通文件

$   echo 'hello shiyanlou' > redirect

$   cat redirect

    

 

初学者这里要注意不要将管道和重定向混淆,管道默认是连接前一个命令的输出到下一个命令的输入,而重定向通常是需要一个文件来建立两个命令的连接,你可以仔细体会一下上述第三个操作和最后两个操作的异同点。

 

2.标准错误重定向

重定向标准输出到文件,这是一个很实用的操作,另一个很实用的操作是将标准错误重定向,标准输出和标准错误都被指向伪终端的屏幕显示,所以我们经常看到的一个命令的输出通常是同时包含了标准输出和标准错误的结果的。比如下面的操作:

 

# 使用cat 命令同时读取两个文件,其中一个存在,另一个不存在

$   cat Documents/test.c\~ hello.c

# 你可以看到除了正确输出了前一个文件的内容,还在末尾出现了一条错误信息

# 下面我们将输出重定向到一个文件,根据我们前面的经验,这里将在看不到任何输出了

$   cat Documents/test.c\~ hello.c > somefile

    

 

遗憾的是,这里依然出现了那条错误信息,这正是因为如我上面说的那样,标准输出和标准错误虽然都指向终端屏幕,实际它们并不一样。那有的时候我们就是要可以隐藏某些错误或者警告,那又该怎么做呢。这就需要用到我们前面讲的文件描述符了:

 

# 将标准错误重定向到标准输出,再将标准输出重定向到文件,注意要将重定向到文件写到前面

$   cat Documents/test.c\~ hello.c >somefile    2>&1

# 或者只用bash提供的特殊的重定向符号"&"将标准错误和标准输出同时重定向到文件

$   cat Documents/test.c\~ hello.c &>somefilehell

注意你应该在输出重定向文件描述符前加上&,否则shell会当做重定向到一个文件名为1的文件中

    

 

 

3.使用tee命令同时重定向到多个文件

经常你可能还有这样的需求,除了将需要将输出重定向到文件之外也需要将信息打印在终端,那么你可以使用tee命令来实现:

$   echo 'hello shiyanlou' | tee hello

    

 

4.永久重定向

你应该可以看出我们前面的重定向操作都只是临时性的,即只对当前命令有效,那如何做到“永久”有效呢,比如在一个脚本中,你需要某一部分的命令的输出全部进行重定向,难道要让你在每个命令上面加上临时重定向的操作嘛,当然不需要,我们可以使用exec命令实现“永久”重定向。exec命令的作用是使用指定的命令替换当前的 Shell,及使用一个进程替换当前进程,或者指定新的重定向:

 

# 先开启一个子   Shell

$   zsh

# 使用exec替换当前进程的重定向,将标准输出重定向到一个文件

$   exec 1>somefile

# 后面你执行的命令的输出都将被重定向到文件中,直到你退出当前子shell,或取消exec的重定向(后面将告诉你怎么做)

$ ls

$   exit

$   cat somefile

    

 

5.创建输出文件描述符

默认在 Shell 中可以有9个打开的文件描述符,上面我们使用了也是它默认提供的0,1,2号文件描述符,另外我们还可以使用3-8的文件描述符。

l  查看当前 Shell 进程中打开的文件描述符:

$ cd   /dev/fd/;ls –Al

    

 

l  同样使用exec命令可以创建新的文件描述符:

$   zsh

$   exec 3>somefile

# 先进入目录,再查看,否则你可能不能得到正确的结果,然后再回到上一次的目录

$ cd   /dev/fd/;ls -Al;cd -

# 注意下面的命令>与&之间不应该有空格,如果有空格则会出错

$   echo "this is test" >&3

$   cat somefile

$   exit

    

 

6.关闭文件描述符

如上面我们打开的3号文件描述符,可以使用如下操作将它关闭:

$   exec 3>&-

$ cd   /dev/fd;ls -Al;cd –

    

 

7.完全屏蔽命令的输出

在 Linux 中有一个被成为“黑洞”的设备文件,所以导入它的数据都将被“吞噬”。在类 UNIX 系统中,/dev/null,或称空设备,是一个特殊的设备文件,它通常被用于丢弃不需要的输出流,或作为用于输入流的空文件,这些操作通常由重定向完成。读取它则会立即得到一个EOF

我们可以利用设个/dev/null屏蔽命令的输出:

$   cat Documents/test.c\~ nefile 1>/dev/null 2>&1

向上面这样的操作将使你得不到任何输出结果。

 

8.使用 xargs 分割参数列表

xargs 是一条 UNIX 和类 UNIX 操作系统的常用命令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题

这个命令在有些时候十分有用,特别是当用来处理产生大量输出结果的命令如 findlocate grep 的结果

$   cut -d: -f1 < /etc/passwd | sort | xargs echo

    

上面这个命令用于将/etc/passwd文件按:分割取第一个字段排序后,使用echo命令生成一个列表。

 

第11节     正则表达式基础

grepsedawk

 

一、正则表达式

什么是正则表达式呢?

正则表达式,又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法(英语:Regular   Expression,在代码中常简写为 regex、regexp 或 RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在 Perl 中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由 UNIX 中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“regex”,单数有 regexp、regex,复数有 regexps、regexes、regexen。

简单的说形式和功能上正则表达式和我们前面讲的通配符很像,不过它们之间又有很大差别,特别在于一些特殊的匹配字符的含义上,希望初学者注意不要将两者弄混淆。

 

1. 举例

假设我们有这样一个文本文件,包含"shiyanlou",和"shilouyan"这两个字符串,同样一个表达式:

shi*

如果这作为一个正则表达式,它将只能匹配 shi,而如果不是作为正则表达式*作为一个通配符,则将同时匹配这两个字符串。这是为什么呢?因为在正则表达式中*表示匹配前面的子表达式(这里就是它前面一个字符)零次或多次,比如它可以匹配"sh","shii","shish","shiishi"等等,而作为通配符表示匹配通配符后面任意多个任意字符,所以它可以匹配"shiyanlou",和"shilouyan"两个字符。

 

2.基本语法:

一个正则表达式通常被称为一个模式(pattern),为用来描述或者匹配一系列符合某个句法规则的字符串。

l  选择

|竖直分隔符表示选择,例如"boy|girl"可以匹配"boy"或者"girl"

 

l  数量限定

数量限定除了我们举例用的*,还有+加号,?问号,.点号,如果在一个模式中不加数量限定符则表示出现一次且仅出现一次:

+表示前面的字符必须出现至少一次(1次或多次),例如,"goo+gle",可以匹配"gooogle","goooogle"等;

?表示前面的字符最多出现一次(0次或1次),例如,"colou?r",可以匹配"color"或者"colour";

*星号代表前面的字符可以不出现,也可以出现一次或者多次(0次、或1次、或多次),例如,“0*42”可以匹配42、042、0042、00042等。

 

l  范围和优先级

()圆括号可以用来定义模式字符串的范围和优先级,这可以简单的理解为是否将括号内的模式串作为一个整体。例如,"gr(a|e)y"等价于"gray|grey",(这里体现了优先级,竖直分隔符用于选择a或者e而不是gra和ey),"(grand)?father"匹配father和grandfather(这里体验了范围,?将圆括号内容作为一个整体匹配)。

 

l  语法(部分)

正则表达式有多种不同的风格,下面列举一些常用的作为 PCRE 子集的适用于perl和python编程语言及grep或egrep的正则表达式匹配规则:

                                                                                                                                                                                                                                                  
    

字符

    
    

描述

    
   

\

   
   

将下一个字符标记为一个特殊字符、或一个原义字符。例如,“n”匹配字符“n”。“\n”匹配一个换行符。序列“\\”匹配“\”而“\(”则匹配“(”。

   
   

^

   
   

匹配输入字符串的开始位置。

   
   

$

   
   

匹配输入字符串的结束位置。

   
   

{n}

   
   

n是一个非负整数。匹配确定的n。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。

   
   

{n,}

   
   

n是一个非负整数。至少匹配n。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。

   
   

{n,m}

   
   

m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。

   
   

*

   
   

匹配前面的子表达式零次或多次。例如,zo*能匹配“z”、“zo”以及“zoo”。*等价于{0,}。

   
   

+

   
   

匹配前面的子表达式一次或多次。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。

   
   

?

   
   

匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”中的“do”。?等价于{0,1}。

   
   

?

   
   

当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。

   
   

.

   
   

匹配除“\n”之外的任何单个字符。要匹配包括“\n”在内的任何字符,请使用像“(.|\n)”的模式。

   
   

(pattern)

   
   

匹配pattern并获取这一匹配的子字符串。该子字符串用于向后引用。要匹配圆括号字符,请使用“\(”或“\)”。

   
   

x|y

   
   

匹配xy。例如,“z|food”能匹配“z”或“food”。“(z|f)ood”则匹配“zood”或“food”。

   
   

[xyz]

   
   

字符集合(character class)。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。其中特殊字符仅有反斜线\保持特殊含义,用于转义字符。其它特殊字符如星号、加号、各种括号等均作为普通字符。脱字符^如果出现在首位则表示负值字符集合;如果出现在字符串中间就仅作为普通字符。连字符 - 如果出现在字符串中间表示字符范围描述;如果如果出现在首位则仅作为普通字符。

   
   

[^xyz]

   
   

排除型(negate)字符集合。匹配未列出的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”。

   
   

[a-z]

   
   

字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。

   
   

[^a-z]

   
   

排除型的字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。

   

 

l  优先级

优先级为从上到下从左到右,依次降低:

                                                                                      
    

运算符

    
    

说明

    
   

\

   
   

转义符

   
   

(), (?:), (?=),     []

   
   

括号和中括号

   
   

*、+、?、{n}、{n,}、{n,m}

   
   

限定符

   
   

^、$、\任何元字符

   
   

定位点和序列

   
   

   
   

 选择

   

 

 

二、grep模式匹配命令

1.基本操作

grep命令用于打印输出文本中匹配的模式串,它使用正则表达式作为模式匹配的条件。grep支持三种正则表达式引擎,分别用三个参数指定:

 

参数   说明

-E  POSIX扩展正则表达式,ERE

-G  POSIX基本正则表达式,BRE

-P  Perl正则表达式,PCRE

 

grep命令的常用参数:

 

参数   说明

-b  将二进制文件作为文本来进行匹配

-c  统计以模式匹配的数目

-i  忽略大小写

-n  显示匹配文本所在行的行号

-v  反选,输出不匹配行的内容

-r  递归匹配查找

-A n      n为正整数,表示after的意思,除了列出匹配行之外,还列出后面的n行

-B n  n为正整数,表示before的意思,除了列出匹配行之外,还列出前面的n行

--color=auto  将输出中的匹配项设置为自动颜色显示

注:在大多数发行版中是默认设置了grep的颜色的,你可以通过参数指定或修改GREP_COLOR环境变量。

 

2.使用正则表达式

使用基本正则表达式,BRE

l  位置

查找/etc/group文件中以"shiyanlou"为开头的行

$   grep 'shiyanlou' /etc/group

$   grep '^shiyanlou' /etc/group

 

l  数量

# 将匹配以'z'开头以'o'结尾的所有字符串

$   echo 'zero\nzo\nzoo' | grep 'z.*o'

    

# 将匹配以'z'开头以'o'结尾,中间包含一个任意字符的字符串

$   echo 'zero\nzo\nzoo' | grep 'z.o'

    

# 将匹配以'z'开头,以任意多个'o'结尾的字符串

$   echo 'zero\nzo\nzoo' | grep 'zo*'

    

注意:其中\n为换行符

 

 

l  选择

#   grep默认是区分大小写的,这里将匹配所有的小写字母

$   echo '1234\nabcd' | grep '[a-z]'

# 将匹配所有的数字

$   echo '1234\nabcd' | grep '[0-9]'

# 将匹配所有的数字

$   echo '1234\nabcd' | grep '[[:digit:]]'

# 将匹配所有的小写字母

$   echo '1234\nabcd' | grep '[[:lower:]]'

# 将匹配所有的大写字母

$   echo '1234\nabcd' | grep '[[:upper:]]'

# 将匹配所有的字母和数字,包括0-9,a-z,A-Z

$   echo '1234\nabcd' | grep '[[:alnum:]]'

# 将匹配所有的字母

$   echo '1234\nabcd' | grep '[[:alpha:]]'

    

 

下面包含完整的特殊符号及说明

                                                                                                                                                                                 
    

特殊符号

    
    

说明

    
   

[:alnum:]

   
   

代表英文大小写字节及数字,亦即 0-9, A-Z, a-z

   
   

[:alpha:]

   
   

代表任何英文大小写字节,亦即 A-Z, a-z

   
   

[:blank:]

   
   

代表空白键与 [Tab] 按键两者

   
   

[:cntrl:]

   
   

代表键盘上面的控制按键,亦即包括 CR, LF, Tab, Del.. 等等

   
   

[:digit:]

   
   

代表数字而已,亦即 0-9

   
   

[:graph:]

   
   

除了空白字节 (空白键与 [Tab] 按键) 外的其他所有按键

   
   

[:lower:]

   
   

代表小写字节,亦即 a-z

   
   

[:print:]

   
   

代表任何可以被列印出来的字节

   
   

[:punct:]

   
   

代表标点符号 (punctuation symbol),亦即:" ' ? ! ; : # $...

   
   

[:upper:]

   
   

代表大写字节,亦即 A-Z

   
   

[:space:]

   
   

任何会产生空白的字节,包括空白键, [Tab], CR 等等

   
   

[:xdigit:]

   
   

代表 16 进位的数字类型,因此包括: 0-9, A-F, a-f 的数字与字节

   

注意:之所以要使用特殊符号,是因为上面的[a-z]不是在所有情况下都管用,这还与主机当前的语系有关,即设置在LANG环境变量的值,zh_CN.UTF-8的话[a-z],即为所有小写字母,其它语系可能是大小写交替的如,"a A b   B...z Z",[a-z]中就可能包含大写字母。所以在使用[a-z]时请确保当前语系的影响,使用[:lower:]则不会有这个问题。

 

# 排除字符

$   echo 'geek|good' | grep '[^o]'

    

注意:^放到中括号内为排除字符,否则表示行首。

 

使用扩展正则表达式,ERE

要通过grep使用扩展正则表达式需要加上-E参数,或使用egrep

 

n  数量

# 只匹配"zo"

$   echo 'zero\nzo\nzoo' | grep -E 'zo{1}'

# 匹配以"zo"开头的所有单词

$   echo 'zero\nzo\nzoo' | grep -E 'zo{1,}'

    

注意:推荐掌握{n,m}即可,+,?,*,这几个不太直观,且容易弄混淆。

 

n  选择

# 匹配"www.shiyanlou.com"和"www.google.com"

$   echo 'www.shiyanlou.com\nwww.baidu.com\nwww.google.com' | grep -E   'www\.(shiyanlou|google)\.com'

# 或者匹配不包含"baidu"的内容

$   echo 'www.shiyanlou.com\nwww.baidu.com\nwww.google.com' | grep -Ev   'www\.baidu\.com'

    

注意:因为.号有特殊含义,所以需要转义。

 

 

三、sed 流编辑器

sed常用参数介绍

sed 命令基本格式:

sed [参数]... [执行命令] [输入文件]...

 

# 形如:

$   sed -i '1s/sad/happy/' test # 表示将test文件中第一行的"sad"替换为"happy"

 

参数   说明

-n  安静模式,只打印受影响的行,默认打印输入数据的全部内容

-e  用于在脚本中添加多个执行命令一次执行,在命令行中执行多个命令通常不需要加该参数

-f filename   指定执行filename文件中的命令

-r  使用扩展正则表达式,默认为标准正则表达式

-i  将直接修改输入文件内容,而不是打印到标准输出设备

 

sed编辑器的执行命令(这里”执行“解释为名词)

sed执行命令格式:

[n1][,n2]command

[n1][~step]command

 

# 其中一些命令可以在后面加上作用范围,形如:

$   sed -i 's/sad/happy/g' test # g表示全局范围

$   sed -i 's/sad/happy/4' test # 4表示指定行中的第四个匹配字符串

其中n1,n2表示输入内容的行号,它们之间为,逗号则表示从n1到n2行,如果为~波浪号则表示从n1开始以step为步进的所有行;command为执行动作,下面为一些常用动作指令

命令   说明

s   行内替换

c   整行替换

a   插入到指定行的后面

i   插入到指定行的前面

p   打印指定行,通常与-n参数配合使用

d   删除指定行

 

sed操作举例

1)          我们先找一个用于练习的文本文件:

$ cp   /etc/passwd ~

 

2)          打印指定行

# 打印2-5行

$ nl   passwd | sed -n '2,5p'

# 打印奇数行

$ nl   passwd | sed -n '1~2p'

      

 

3)          行内替换

# 将输入文本中"shiyanlou"   全局替换为"hehe",并只打印替换的那一行,注意这里不能省略最后的"p"命令

$   sed -n 's/shiyanlou/hehe/gp' passwd

    

注意: 行内替换可以结合正则表达式使用。

 

4)          行间替换

$ nl   passwd | grep "shiyanlou"

# 删除第21行

$   sed -n '21c\www.shiyanlou.com' passwd

      

 

四、awk文本处理语言

awk的常用操作:

 

1.awk介绍

系统已经为我们创建好了awk指向mawk的符号链接:

$ ll   /usr/bin/awk

 

 

2.awk的一些基础概念

awk所有的操作都是基于pattern(模式)action(动作)对来完成的,如下面的形式:

$ pattern {action}

 

pattern通常是是表示用于匹配输入的文本的“关系式”或“正则表达式”

action则是表示匹配后将执行的动作

在一个完整awk操作中,这两者可以只有其中一个,如果没有pattern则默认匹配输入的全部文本,如果没有action则默认为打印匹配内容到屏幕

awk处理文本的方式,是将文本分割成一些“字段”,然后再对这些字段进行处理,默认情况下,awk以空格作为一个字段的分割符,不过这不是固定了,你可以任意指定分隔符

 

3.awk命令基本格式

awk [-F fs] [-v   var=value] [-f prog-file | 'program text'] [file...]

-F参数用于预先指定前面提到的字段分隔符

-v用于预先为awk程序指定变量

-f参数用于指定awk命令要执行的程序文件

或者在不加-f参数的情况下直接将程序语句放在这里,最后为awk需要处理的文本输入,且可以同时输入多个文本文件

 

 

4.awk操作体验

先用vim新建一个文本文档

$   vim test

包含如下内容:

I   like linux

www.shiyanlou.com

•     使用awk将文本内容打印到终端

#   "quote>" 不用输入

$   awk '{

>   print

>   }' test

# 或者写到一行

$   awk '{print}' test

 

说明:在这个操作中我是省略了patter,所以awk会默认匹配输入文本的全部内容,然后在"{}"花括号中执行动作,即print打印所有匹配项,这里是全部文本内容

•     将test的第一行的每个字段单独显示为一行

$   awk '{

>   if(NR==1){

>   print $1 "\n" $2 "\n" $3

>   } else {

>   print}

>   }' test

 

# 或者

$   awk '{

>   if(NR==1){

>   OFS="\n"

>   print $1, $2, $3

>   } else {

>   print}

>   }' test

 

•     将test的第二行的以点为分段的字段换成以空格为分隔

$   awk -F'.' '{

>   if(NR==2){

>   print $1 "\t" $2 "\t" $3

>   }}' test

 

# 或者

$   awk '

>   BEGIN{

>   FS="."

>   OFS="\t"  # 如果写为一行,两个动作语句之间应该以";"号分开 

>   }{

>   if(NR==2){

>   print $1, $2, $3

>   }}' test

 

 

6.awk常用的内置变量

                                                                                                                                                       
    

变量名

    
    

说明

    
   

FILENAME

   
   

当前输入文件名,若有多个文件,则只表示第一个。如果输入是来自标准输入,则为空字符串

   
   

$0

   
   

当前记录的内容

   
   

$N

   
   

N表示字段号,最大值为NF变量的值

   
   

FS

   
   

字段分隔符,由正则表达式表示,默认为" "空格

   
   

RS

   
   

输入记录分隔符,默认为"\n",即一行为一个记录

   
   

NF

   
   

当前记录字段数

   
   

NR

   
   

已经读入的记录数

   
   

FNR

   
   

当前输入文件的记录数,请注意它与NR的区别

   
   

OFS

   
   

输出字段分隔符,默认为" "空格

   
   

ORS

   
   

输出记录分隔符,默认为"\n"

   

 

第十二节  Linux 下软件安装

介绍 Ubuntu 下软件安装的几种方式,及 apt,dpkg 工具的使用。

 

一、Linux 上的软件安装

 

通常 Linux 上的软件安装主要有四种方式:

1)          在线安装

2)          从磁盘安装deb软件包

3)          从二进制软件包安装

4)          从源代码编译安装

 

二、在线安装

 

1. 先体验一下

 

比如我们想安装一个软件,名字叫做 w3m(w3m是一个命令行的简易网页浏览器),那么输入如下命令:

$   sudo apt-get install w3m

这样的操作你应该在前面的章节中看到过很多次了,它就表示将会安装一个软件包名为w3m的软件

$   w3m www.shiyanlou.com/faq

注意:如果你在安装一个软件之后,无法立即使用Tab键补全这可命令,你可以尝试先执行source ~/.zshrc,然后你就可以使用补全操作。

 

2. apt 包管理工具介绍

APT是Advance Packaging Tool(高级包装工具)的缩写,是Debian及其派生发行版的软件包管理器,APT可以自动下载,配置,安装二进制或者源代码格式的软件包,因此简化了Unix系统上管理软件的过程。APT最早被设计成dpkg的前端,用来处理deb格式的软件包。现在经过APT-RPM组织修改,APT已经可以安装在支持RPM的系统管理RPM包。这个包管理器包含以 apt- 开头的的多个工具,如 apt-get apt-cache apt-cdrom 等,在Debian系列的发行版中使用。

当你在执行安装操作时,首先apt-get 工具会在本地的一个数据库中搜索关于 w3m 软件的相关信息,并根据这些信息在相关的服务器上下载软件安装,这里大家可能会一个疑问:既然是在线安装软件,为啥会在本地的数据库中搜索?要解释这个问题就得提到几个名词了:

软件源镜像服务器

软件源

我们需要定期从服务器上下载一个软件包列表,使用 sudo apt-get update 命令来保持本地的软件包列表是最新的(有时你也需要手动执行这个操作,比如更换了软件源),而这个表里会有软件依赖信息的记录,对于软件依赖,我举个例子:我们安装 w3m 软件的时候,而这个软件需要 libgc1c2 这个软件包才能正常工作,这个时候 apt-get 在安装软件的时候会一并替我们安装了,以保证 w3m 能正常的工作。

 

3.apt-get

apt-get使用各用于处理apt包的公用程序集,我们可以用它来在线安装、卸载和升级软件包等,下面列出一些apt-get包含的常用的一些工具

                                                                                                                                          
    

工具

    
    

说明

    
   

install

   
   

其后加上软件包名,用于安装一个软件包

   
   

update

   
   

从软件源镜像服务器上下载/更新用于更新本地软件源的软件包列表

   
   

upgrade

   
   

升级本地可更新的全部软件包,但存在依赖问题时将不会升级,通常会在更新之前执行一次update

   
   

dist-upgrade

   
   

解决依赖关系并升级(存在一定危险性)

   
   

remove

   
   

移除已安装的软件包,包括与被移除软件包有依赖关系的软件包,但不包含软件包的配置文件

   
   

autoremove

   
   

移除之前被其他软件包依赖,但现在不再被使用的软件包

   
   

purge

   
   

与remove相同,但会完全移除软件包,包含其配置文件

   
   

clean

   
   

移除下载到本地的已经安装的软件包,默认保存在/var/cache/apt/archives/

   
   

autoclean

   
   

移除已安装的软件的旧版本软件包

   

下面是一些apt-get常用的参数:

                                                                                                                
    

参数

    
    

说明

    
   

-y

   
   

自动回应是否安装软件包的选项,在一些自动化安装脚本中使用这个参数将十分有用

   
   

-s

   
   

模拟安装

   
   

-q

   
   

静默安装方式,指定多个q或者-q=#,#表示数字,用于设定静默级别,这在你不想要在安装软件包时屏幕输出过多时很有用

   
   

-f

   
   

修复损坏的依赖关系

   
   

-d

   
   

只下载不安装

   
   

--reinstall

   
   

重新安装已经安装但可能存在问题的软件包

   
   

--install-suggests

   
   

同时安装APT给出的建议安装的软件包

   

 

4.安装软件包

关于安装,如前面演示的一样你只需要执行apt-get install <软件包名>即可,除了这一点,你还应该掌握的是如何重新安装软件包。 很多时候我们需要重新安装一个软件包,比如你的系统被破坏,或者一些错误的配置导致软件无法正常工作。

你可以使用如下方式重新安装:

$   sudo apt-get --reinstall install w3m

 

另一个你需要掌握的是,如何在不知道软件包完整名的时候进行安装。通常我们是使用Tab键补全软件包名,后面会介绍更好的方法来搜索软件包。有时候你需要同时安装多个软件包,你还可以使用正则表达式匹配软件包名进行批量安装。

 

5.软件升级

# 更新软件源

$   sudo apt-get update

# 升级没有依赖问题的软件包

$   sudo apt-get upgrade

# 升级并解决依赖关系

$   sudo apt-get dist-upgrade

 

6.卸载软件

如果你现在觉得 w3m 这个软件不合自己的胃口,或者是找到了更好的,你需要卸载它,那么简单!同样是一个命令加回车 sudo   apt-get remove w3m ,系统会有一个确认的操作,之后这个软件便“滚蛋了”。

 

或者,你可以执行

# 不保留配置文件的移除

$   sudo apt-get purge w3m

# 或者   sudo apt-get --purge remove

# 移除不再需要的被依赖的软件包

$   sudo apt-get autoremove

 

7.软件搜索

 

当自己刚知道了一个软件,想下载使用,需要确认软件仓库里面有没有,就需要用到搜索功能了,命令如下:

sudo   apt-cache search softname1 softname2 softname3……

apt-cache 命令则是针对本地数据进行相关操作的工具,search 顾名思义在本地的数据库中寻找有关 softname1   softname2 …… 相关软件的信息。现在我们试试搜索一下之前我们安装的软件 w3m ,如图:

    

结果显示了4个 w3m 相关的软件,并且有相关软件的简介。

 

三、使用 dpkg 从本地磁盘安装 deb 软件包

 

1.dpkg 介绍

dpkg 是 Debian 软件包管理器的基础,它被伊恩·默多克创建于 1993 年。dpkg 与 RPM 十分相似,同样被用于安装、卸载和供给和 .deb 软件包相关的信息。

dpkg 本身是一个底层的工具。上层的工具,像是 APT,被用于从远程获取软件包以及处理复杂的软件包关系。"dpkg"是"Debian Package"的简写。

我们经常可以在网络上简单以deb形式打包的软件包,就需要使用dpkg命令来安装。

 

dpkg常用参数介绍:

                                                                                                                
    

参数

    
    

说明

    
   

-i

   
   

安装指定deb包

   
   

-R

   
   

后面加上目录名,用于安装该目录下的所有deb安装包

   
   

-r

   
   

remove,移除某个已安装的软件包

   
   

-I

   
   

显示deb包文件的信息

   
   

-s

   
   

显示已安装软件的信息

   
   

-S

   
   

搜索已安装的软件包

   
   

-L

   
   

显示已安装软件包的目录信息

   

 

2.使用dpkg安装deb软件包

我们先使用apt-get加上-d参数只下载不安装,下载emacs编辑器的deb包,下载完成后,我们可以查看/var/cache/apt/archives/目录下的内容,如下图:

 

然后我们将第一个deb拷贝到home目录下,并使用dpkg安装

$ cp   /var/cache/apt/archives/emacs24_24.3+1-4ubuntu1_amd64.deb ~

# 安装之前参看deb包的信息

$   sudo dpkg -I emacs24_24.3+1-4ubuntu1_amd64.deb

如你所见,这个包还额外依赖了一些软件包,这意味着,如果主机目前没有这些被依赖的软件包,直接使用dpkg安装可能会存在一些问题,因为dpkg并不能为你解决依赖关系。

# 使用dpkg安装

$   sudo dpkg -i emacs24_24.3+1-4ubuntu1_amd64.deb

这里可能会出现一些错误,用apt-get的-f参数,修复依赖关系的安装

$   sudo apt-get -f install

这样我们就安装成功了,然后可以运行emacs程序

 

3.查看已安装软件包的安装目录

如果你依然在纠结到底linux将软件安装到了什么地方,那么很幸运你将可以通过dpkg找到答案

使用dpkg -L查看deb包目录信息

$   sudo dpkg -L emacs

 

 

四、从二进制包安装

 

二进制包的安装比较简单,我们需要做的只是将从网络上下载的二进制包解压后放到合适的目录,然后将包含可执行的主程序文件的目录添加进PATH环境变量即可,如果你不知道该放到什么位置,请重新复习第四节关于 Linux 目录结构的内容。

 

 

七、遇到的问题及解决

1)          1.创建一个 Shell 脚本文件:

$ vim hello_shell.sh

2)          在脚本中添加如下内容,保存并退出(注意不要省掉第一行,这不是注释,论坛有用户反应会有语法错误,就是因为没有了第一行):

#!/bin/zsh

for ((i=0; i<10; i++));do

    echo "hello shell"

done

exit 0

???怎么退出bash啊!!!】这个问题我依旧没有解决……

2.在实验楼里跟着做能做下来,但是并不能真正迁移到自己的虚拟机中

3.虚拟硬盘那里不太能理解


 
 


 
 

 

 

八、其他

Linux学的我云里雾里……虽然这个实验课跟完了但是并没有多大的用处……没有得到多少真正的知识,只是填鸭一样的做完了就完了,这个系统体系需要从头到尾的知识讲解,慢慢体会理解才行啊,罗马不是一天建成的,只能慢慢来了……

posted @ 2015-09-20 22:07  20135202闫佳歆  阅读(433)  评论(1编辑  收藏  举报