鸟哥的Linux私房菜学习笔记(三)学习 Shell 与 Shell scripts——认识与学习 BASH

1.认识BASH这个Shell

1)硬件、核心与 Shell

管理整个计算机硬件的其实是操作系统的核心 (kernel),般使用者就只能透过 shell 来跟核心沟通

2)系统的合法 shell 与 /etc/shells 功能

由于早年的 Unix 年代,发展者众,所以由于 shell 依据发展者的不同就有许多的版本,至于 Linux 使用的这一种版本就称为『 Bourne Again SHell (简称 bash) 』

系统上合法的 shell 写入在/etc/shells 文件,系统某些服务在运行过程中,会去检查使用者能够使用的 shells ,而这些 shell 的查询就是藉由 /etc/shells 这个文件。

当我登陆的时候,系统就会给我一个 shell 让我来工作了。 而这个登陆取得的 shell 就记录在 /etc/passwd 这个文件内!

3)Bash shell 的功能

命令编修能力 (history):能够记录使用过的命令,在家目录内的 .bash_history 。~/.bash_history 记录的是前一次登陆以前所运行过的命令, 而至于这一次登陆所运行的命令都被缓存在内存中,当你成功的注销系统后,该命令记忆才会记录到 .bash_history 当中!

命令与文件补全功能: ([tab] 按键的好处)

命令别名配置功能: (alias) 例如,alias lm='ls -al'

工作控制、前景背景控制: (job control, foreground, background)

程序化脚本: (shell scripts) Linux 底下的 shell scripts 则发挥更为强大的功能,可以将你平时管理系统常需要下达的连续命令写成一个文件, 该文件并且可以透过对谈交互式的方式来进行主机的侦测工作!也可以藉由 shell 提供的环境变量及相关命令来进行设计

通配符: (Wildcard)除了完整的字符串之外, bash 还支持许多的通配符来帮助用户查询与命令下达。 举例来说,想要知道 /usr/bin 底下有多少以 X 为开头的文件吗?使用:『 ls -l /usr/bin/X* 』就能够知道啰~

4)Bash shell 的内建命令: type 

为了方便 shell 的操作,其实 bash 已经『内建』了很多命令了。那我怎么知道这个命令是来自于外部命令(指的是其他非 bash 所提供的命令) 或是内建在 bash 当中的呢? 嘿嘿!利用 type 这个命令来观察即可!

5)命令的下达

『 \[Enter] 』来将 [Enter] 这个按键『跳脱!』开来,让 [Enter] 按键不再具有『开始运行』的功能!好让命令可以继续在下一行输入。

如果顺利跳脱 [Enter] 后,下一行最前面就会主动出现 > 的符号, 你可以继续输入命令啰!

2.Shell 的变量功能

1)什么是变量

影响 bash 环境操作的变量,环境变量例如 PATH、HOME、MAIL、SHELL 等等,都是很重要的, 为了区别与自定义变量的不同,环境变量通常以大写字符来表示呢!

脚本程序设计 (shell script) 的好帮手。

2)变量的取用与配置:echo, 变量配置守则, unset

变量的取用echo:变量在被取用时,前面必须要加上『 $ 』才行


利用 echo 就能够读出,只是需要在变量名称前面加上 $ , 或者是以 ${变量} 的方式来取用都可以!

『配置』或者是『修改』 某个变量的内容,用『等号(=)』连接变量与他的内容就好啦!


变量的配置守则:
    1.变量与变量内容以一个等号『=』来连结,如下所示: 
        『myname=VBird』
    2.等号两边不能直接接空格符,如下所示为错误: 
        『myname = VBird』或『myname=VBird Tsai』
    3.变量名称只能是英文字母与数字,但是开头字符不能是数字,如下为错误: 
        『2myname=VBird』
    4.变量内容若有空格符可使用双引号『"』或单引号『'』将变量内容结合起来,但双引号内的特殊字符如 $ 等,可以保有原本的特性,如下所示:
        『var="lang is $LANG"』则『echo $var』可得『lang is en_US』
       单引号内的特殊字符则仅为一般字符 (纯文本),如下所示:
        『var='lang is $LANG'』则『echo $var』可得『lang is $LANG』
    5.可用跳脱字符『 \ 』将特殊符号(如 [Enter], $, \, 空格符, '等)变成一般字符;
    6.在一串命令中,还需要藉由其他的命令提供的信息,可以使用反单引号『`命令`』或 『$(命令)』。特别注意,那个 ` 是键盘上方的数字键 1 左边那个按键,而不是单引号! 例如想要取得核心版本的配置:
        『version=$(uname -r)』再『echo $version』可得『2.6.18-128.el5』
    7.若该变量为扩增变量内容时,则可用 "$变量名称" 或 ${变量} 累加内容,如下所示:
        『PATH="$PATH":/home/bin』
    8.若该变量需要在其他子程序运行,则需要以 export 来使变量变成环境变量:
        『export PATH』
    9.通常大写字符为系统默认变量,自行配置变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;
    10.取消变量的方法为使用 unset :『unset 变量名称』例如取消 myname 的配置:
    HOME
    SHELL
    HISTSIZE
    MAIL
    PATH
    LANG
    RANDOM
    PS1:(提示字符的配置)
好了,让我们来看看 CentOS 默认的 PS1 内容吧:『[\u@\h \W]\$ 』,现在你知道那些反斜杠后的数据意义了吧? 要注意喔!那个反斜杠后的数据为 PS1 的特殊功能,与 bash 的变量配置没关系啦!不要搞混了喔! 那你现在知道为何你的命令提示字符是:『 [root@www ~]# 』了吧? 好了,那么假设我想要有类似底下的提示字符:root@www /home/dmtsai 16:50 #12]#
    $:(关于本 shell 的 PID)
    $字号本身也是个变量喔!这个咚咚代表的是『目前这个 Shell 的线程代号』,亦即是所谓的 PID (Process ID)。 更多的程序观念,我们会在第四篇的时候提及。想要知道我们的 shell 的 PID ,就可以用:『 echo $$ 』即可!出现的数字就是你的 PID 号码。
    ?:(关于上个运行命令的回传值)
    变量类型默认为『字符串』;
    bash 环境中的数值运算,默认最多仅能到达整数形态,所以 1/3 结果是 0;
    PATH:会依据 UID 决定 PATH 变量要不要含有 sbin 的系统命令目录;
    MAIL:依据账号配置好使用者的 mailbox 到 /var/spool/mail/账号名;
    USER:根据用户的账号配置此一变量内容;
    HOSTNAME:依据主机的 hostname 命令决定此一变量内容;
    ~/.bash_profile
    ~/.bash_login
    eof   : End of file 的意思,代表『结束输入』。
    erase : 向后删除字符,
    intr  : 送出一个 interrupt (中断) 的讯号给目前正在 run 的程序;
    kill  : 删除在目前命令列上的所有文字;
    quit  : 送出一个 quit 的讯号给目前正在 run 的程序;
    start : 在某个程序停止后,重新启动他的 output
    stop  : 停止目前屏幕的输出;
    Ctrl + C 终止目前的命令
    Ctrl + D 输入结束 (EOF),例如邮件结束的时候;
    Ctrl + M 就是 Enter 啦!
    Ctrl + S 暂停屏幕的输出
    Ctrl + Q 恢复屏幕的输出
    Ctrl + U 在提示字符下,将整列命令删除
    * 代表『 0 个到无穷多个』任意字符
    ? 代表『一定有一个』任意字符
    [ ] 同样代表『一定有一个在括号内』的字符(非任意字符)。例如 [abcd] 代表『一定有一个字符, 可能是 a, b, c, d 这四个任何一个』
    [ - ] 若有减号在中括号内时,代表『在编码顺序内的所有字符』。例如 [0-9] 代表 0 到 9 之间的所有数字,因为数字的语系编码是连续的!
    \ 跳脱符号:将『特殊字符或通配符』还原成一般字符
    | 管线 (pipe):分隔两个管线命令的界定(后两节介绍);
    ; 连续命令下达分隔符:连续性命令的界定 (注意!与管线命令并不相同)
    ~ 用户的家目录
    $ 取用变量前导符:亦即是变量之前需要加的变量取代值
    & 工作控制 (job control):将命令变成背景下工作
    ! 逻辑运算意义上的『非』 not 的意思!
    / 目录符号:路径分隔的符号
    >, >> 数据流重导向:输出导向,分别是『取代』与『累加』
    <, << 数据流重导向:输入导向 (这两个留待下节介绍)
    ' ' 单引号,不具有变量置换的功能
    " " 具有变量置换的功能!
    ` ` 两个『 ` 』中间为可以先运行的命令,亦可使用 $( )
    ( ) 在中间为子 shell 的起始与结束
    { } 在中间为命令区块的组合!
    标准输入  (stdin) :代码为 0 ,使用 < 或 << ;
    标准输出  (stdout):代码为 1 ,使用 > 或 >> ;
该文件 (本例中是 ~/rootfile) 若不存在,系统会自动的将他创建起来,但是当这个文件存在的时候,那么系统就会先将这个文件内容清空,然后再将数据写入!
    屏幕输出的信息很重要,而且我们需要将他存下来的时候;
    背景运行中的程序,不希望他干扰屏幕正常的输出结果时;
    一些系统的例行命令 (例如写在 /etc/crontab 中的文件) 的运行结果,希望他可以存下来时;
    一些运行命令的可能已知错误信息时,想以『 2> /dev/null 』将他丢掉时;
    错误信息与正确信息需要分别输出时。

上面这个例子是说:『我将 /home 里面的文件给他打包,但打包的数据不是纪录到文件,而是传送到 stdout; 经过管线后,将 tar -cvf - /home 传送给后面的 tar -xvf - 』。后面的这个 - 则是取用前一个命令的 stdout, 因此,我们就不需要使用 file 了!这是很常见的例子喔!注意注意!

        『unset myname』

什么是『子程序』呢?就是说,在我目前这个 shell 的情况下,去激活另一个新的 shell ,新的那个 shell 就是子程序啦!在一般的状态下,父程序的自定义变量是无法在子程序内使用的。但是透过 export 将变量变成环境变量后,就能够在子程序底下应用了!



单引号与双引号的最大不同在于双引号仍然可以保有变量的内容,但单引号内仅能是一般字符 ,而不会有特殊符号。

在一串命令中,在单引号之内的命令将会被先运行,而其运行出来的结果将做为外部的输入信息!例如:root@www ~]# ls -l `locate crontab`

若你有一个常去的工作目录名称为:『/cluster/server/work/taiwan_2005/003/』,如何进行该目录的简化?

    [root@www ~]# work="/cluster/server/work/taiwan_2005/003/"

    [root@www ~]# cd $work

3)环境变量的功能

env 观察环境变量与常见环境变量说明


那么上面这些变量有些什么功用呢?底下我们就一个一个来分析分析!

    代表用户的家目录。还记得我们可以使用 cd ~ 去到自己的家目录吗?或者利用 cd 就可以直接回到用户家目录了。那就是取用这个变量啦~ 有很多程序都可能会取用到这个变量的值!

    告知我们,目前这个环境使用的 SHELL 是哪支程序? Linux 默认使用 /bin/bash 的啦!

    这个与『历史命令』有关,亦即是, 我们曾经下达过的命令可以被系统记录下来,而记录的『笔数』则是由这个值来配置的。

    当我们使用 mail 这个命令在收信时,系统会去读取的邮件信箱文件 (mailbox)。

    就是运行文件搜寻的路径啦~目录与目录中间以冒号(:)分隔, 由于文件的搜寻是依序由 PATH 的变量内的目录来查询,所以,目录的顺序也是重要的喔。

    这个重要!就是语系数据啰~很多信息都会用到他, 举例来说,当我们在启动某些 perl 的程序语言文件时,他会主动的去分析语系数据文件, 如果发现有他无法解析的编码语系,可能会产生错误喔!一般来说,我们中文编码通常是 zh_TW.Big5 或者是 zh_TW.UTF-8,这两个编码偏偏不容易被解译出来,所以,有的时候,可能需要修订一下语系数据。 这部分我们会在下个小节做介绍的!

这个玩意儿就是『随机随机数』的变量啦!目前大多数的 distributions 都会有随机数生成器,那就是 /dev/random 这个文件。 我们可以透过这个随机数文件相关的变量 ($RANDOM) 来随机取得随机数值喔。在 BASH 的环境下,这个 RANDOM 变量的内容,介于 0~32767 之间,所以,你只要 echo $RANDOM 时,系统就会主动的随机取出一个介于 0~32767 的数值。万一我想要使用 0~9 之间的数值呢?呵呵~利用 declare 宣告数值类型, 然后这样做就可以了:


set 观察所有变量 (含环境变量与自定义变量)

bash 可不只有环境变量喔,还有一些与 bash 操作接口有关的变量,以及用户自己定义的变量存在的 那么这些变量如何观察呢?这个时候就得要使用 set 这个命令了。


    这是 PS1 (数字的 1 不是英文字母),这个东西就是我们的『命令提示字符』喔! 当我们每次按下 [Enter] 按键去运行某个命令后,最后要再次出现提示字符时, 就会主动去读取这个变量值了。上头 PS1 内显示的是一些特殊符号,这些特殊符号可以显示不同的信息, 每个 distributions 的 bash 默认的 PS1 变量内容可能有些许的差异,不要紧,『习惯你自己的习惯』就好了。 你可以用 man bash (注3)去查询一下 PS1 的相关说明,以理解底下的一些符号意义。

\d :可显示出『星期 月 日』的日期格式,如:"Mon Feb 2"

\H :完整的主机名。举例来说,鸟哥的练习机为『www.vbird.tsai』

\h :仅取主机名在第一个小数点之前的名字,如鸟哥主机则为『www』后面省略

\t :显示时间,为 24 小时格式的『HH:MM:SS』

\T :显示时间,为 12 小时格式的『HH:MM:SS』

\A :显示时间,为 24 小时格式的『HH:MM』

\@ :显示时间,为 12 小时格式的『am/pm』样式

\u :目前使用者的账号名称,如『root』;

\v :BASH 的版本信息,如鸟哥的测试主板本为 3.2.25(1),仅取『3.2』显示

\w :完整的工作目录名称,由根目录写起的目录名称。但家目录会以 ~ 取代;

\W :利用 basename 函数取得工作目录名称,所以仅会列出最后一个目录名。

\# :下达的第几个命令。

\$ :提示字符,如果是 root 时,提示字符为 # ,否则就是 $ 啰~

    问号也是一个特殊的变量?没错!在 bash 里面这个变量可重要的很! 这个变量是:『上一个运行的命令所回传的值』, 上面这句话的重点是『上一个命令』与『回传值』两个地方。当我们运行某些命令时, 这些命令都会回传一个运行后的代码。一般来说,如果成功的运行该命令, 则会回传一个 0 值,如果运行过程发生错误,就会回传『错误代码』才对!一般就是以非为 0 的数值来取代。 我们以底下的例子来看看:

    OSTYPE, HOSTTYPE, MACHTYPE:(主机硬件与核心的等级)

export: 自定义变量转成环境变量

子程序仅会继承父程序的环境变量, 子程序不会继承父程序的自定义变量啦!

如果我能将自定义变量变成环境变量的话,那不就可以让该变量值继续存在于子程序了? 呵呵!没错!这东西用在『分享自己的变量配置给后来呼叫的文件或其他程序』啦!

export [变量名称]=

如果仅下达 export 而没有接变量时,那么此时将会把所有的『环境变量』秀出来喔!

4)影响显示结果的语系变量 (locale)

Linux 到底支持了多少的语系呢?这可以由 locale 这个命令来查询到喔!

整体系统默认的语系定义在哪里呢? 其实就是在 /etc/sysconfig/i18n 啰!

5)变量的有效范围

在某些不同的书籍会谈到『全局变量, global variable』与『局部变量, local variable』。 基本上你可以这样看待:

    环境变量=全局变量

    自定义变量=局部变量

6)变量键盘读取、数组与宣告: read, array, declare

上面提到的变量配置功能,都是由命令列直接配置的,那么,可不可以让用户能够经由键盘输入? 什么意思呢?是否记得某些程序运行的过程当中,会等待使用者输入 "yes/no" 之类的信息啊? 在 bash 里面也有相对应的功能喔!此外,我们还可以宣告这个变量的属性, 例如:数组或者是数字等等的。

read 

要读取来自键盘输入的变量


declare / typeset 

declare 或 typeset 是一样的功能,就是在『宣告变量的类型』。如果使用 declare 后面并没有接任何参数,那么 bash 就会主动的将所有的变量名称与内容通通叫出来,就好像使用 set 一样啦!


由于在默认的情况底下, bash 对于变量有几个基本的定义:


比较有趣的是,如果你不小心将变量配置为『只读』,通常得要注销再登陆才能复原该变量的类型了!

在 bash 里头,数组的配置方式是:var[index]=content


7)与文件系统及程序的限制关系: ulimit

bash 是可以『限制用户的某些系统资源』的,包括可以开启的文件数量, 可以使用的 CPU 时间,可以使用的内存总量等等。如何配置?用 ulimit 吧!

8)变量内容的删除、取代与替换

变量内容的删除与取代

变量的测试与内容替换

3.命令别名与历史命令

1)命令别名配置: alias, unalias

alias 命名别名

alias『别名』='命令 选项...’

命令别名是一个很有趣的东西,特别是你的惯用命令特别长的时候!还有, 增设默认的选项在一些惯用的命令上面,可以预防一些不小心误杀文件的情况发生的时候!

举个例子来说,如果你要查询隐藏档,并且需要长的列出与一页一页翻看,那么需要下达『 ls -al | more 』这个命令,我是觉得很烦啦! 要输入好几个单字!那可不可以使用 lm 来简化呢?当然可以,你可以在命令行下面下达:

    [root@www ~]# alias lm='ls -al | more'

另外,命令别名的配置还可以取代既有的命令喔! rm 提供了一个选项来让我们确认是否要移除该文件,那就是 -i 这个选项!那么以后使用 rm 的时候,就不用太担心会有错误删除的情况了!

    [root@www ~]# alias rm='rm -i'

unalias 取消命令别名

unalias 『别名』

2)历史命令:history

前面我们提过 bash 有提供命令历史的服务!那么如何查询我们曾经下达过的命令呢?就使用 history 啰!


那么 history 这个历史命令只可以让我查询命令而已吗?呵呵!当然不止啊! 我们可以利用相关的功能来帮我们运行命令呢!举例来说啰:


同一账号同时多次登陆的 history 写入问题

有些朋友在练习 linux 的时候喜欢同时开好几个 bash 接口,这些 bash 的身份都是 root 。 这样会有 ~/.bash_history 的写入问题吗?因为这些 bash 在同时以 root 的身份登陆, 因此所有的 bash 都有自己的 1000 笔记录在内存中。因为等到注销时才会升级记录文件,所以啰, 最后注销的那个 bash 才会是最后写入的数据。

无法记录时间

4.认识与学习 BASH 

1)路径与命令搜寻顺序

命令运行的顺序可以这样看(如命令ls):

    以相对/绝对路径运行命令,例如『 /bin/ls 』或『 ./ls 』;

    由 alias 找到该命令来运行;

    由 bash 内建的 (builtin) 命令来运行;

    透过 $PATH 这个变量的顺序搜寻到的第一个命令来运行。

2)bash 的进站与欢迎信息: /etc/issue, /etc/motd

什么! bash 也有进站画面与欢迎信息喔?真假?真的啊! 还记得在终端机接口 (tty1 ~ tty6) 登陆的时候,会有几行提示的字符串吗?那就是进站画面啊!

除了 /etc/issue 之外还有个 /etc/issue.net 呢!这是啥?这个是提供给 telnet 这个远程登录程序用的。 当我们使用 telnet 连接到主机时,主机的登陆画面就会显示 /etc/issue.net 而不是 /etc/issue 呢!

至于如果您想要让使用者登陆后取得一些信息,例如您想要让大家都知道的信息, 那么可以将信息加入 /etc/motd 里面去!

3)环境配置文件: login, non-login shell, /etc/profile, ~/.bash_profile, source, ~/.bashrc

要注意的是, 我们前几个小节谈到的命令别名啦、自定义的变量啦,在你注销 bash 后就会失效,所以你想要保留你的配置, 就得要将这些配置写入配置文件才行。

login 与 non-login shell

login shell:取得 bash 时需要完整的登陆流程的,就称为 login shell。举例来说,你要由 tty1 ~ tty6 登陆,需要输入用户的账号与密码,此时取得的 bash 就称为『 login shell 』啰;

non-login shell:取得 bash 接口的方法不需要重复登陆的举动,举例来说,(1)你以 X window 登陆 Linux 后, 再以 X 的图形化接口启动终端机,此时那个终端接口并没有需要再次的输入账号与密码,那个 bash 的环境就称为 non-login shell了(2)你在原本的 bash 环境下再次下达 bash 这个命令,同样的也没有输入账号密码, 那第二个 bash (子程序) 也是 non-login shell 。

一般来说,login shell 其实只会读取这两个配置文件:

    /etc/profile:这是系统整体的配置,你最好不要修改这个文件;

    ~/.bash_profile 或 ~/.bash_login 或 ~/.profile:属于使用者个人配置,你要改自己的数据,就写入这里!

/etc/profile (login shell 才会读)

这个配置文件可以利用使用者的标识符 (UID) 来决定很多重要的变量数据, 这也是每个使用者登陆取得 bash 时一定会读取的配置文件! 所以如果你想要帮所有使用者配置整体环境,那就是改这里啰!

这个文件配置的变量主要有:

    HISTSIZE:历史命令记录笔数。CentOS 5.x 配置为 1000 ;

/etc/profile 可不止会做这些事而已,他还会去呼叫外部的配置数据喔!

~/.bash_profile (login shell 才会读)

在 login shell 的 bash 环境中,所读取的个人偏好配置文件其实主要有三个,依序分别是:

    ~/.profile

其实 bash 的 login shell 配置只会读取上面三个文件的其中一个, 而读取的顺序则是依照上面的顺序。前面的文件不存在才会读后面的。

source :读入环境配置文件的命令

由于 /etc/profile 与 ~/.bash_profile 都是在取得 login shell 的时候才会读取的配置文件,所以, 如果你将自己的偏好配置写入上述的文件后,通常都是得注销再登陆后,该配置才会生效。那么,能不能直接读取配置文件而不注销登陆呢? 可以的!那就得要利用 source 这个命令了!

举例来说,我修改了 ~/.bashrc ,那么不需要注销,立即以 source ~/.bashrc 就可以将刚刚最新配置的内容读进来目前的环境中!

~/.bashrc (non-login shell 会读)

 当你取得 non-login shell 时,该 bash 配置文件仅会读取 ~/.bashrc 而已啦!

其他相关配置文件

/etc/man.config

规范了使用 man 的时候, man page 的路径到哪里去寻找!

~/.bash_history

默认的情况下, 我们的历史命令就记录在这里啊!而这个文件能够记录几笔数据,则与 HISTFILESIZE 这个变量有关啊。每次登陆 bash 后,bash 会先读取这个文件,将所有的历史命令读入内存, 

~/.bash_logout

这个文件则记录了『当我注销 bash 后,系统再帮我做完什么动作后才离开』

4)终端机的环境配置: stty, set

可以在 tty1 ~ tty6 这六个文字接口的终端机 (terminal) 环境中登陆,登陆的时候我们可以取得一些字符配置的功能喔! 举例来说,我们可以利用退格键 (backspace,就是那个←符号的按键) 来删除命令行上的字符, 也可以使用 [ctrl]+c 来强制终止一个命令的运行,当输入错误时,就会有声音跑出来警告。这是怎么办到的呢? 很简单啊!因为登陆终端机的时候,会自动的取得一些终端机的输入环境的配置啊!

stty

那么如何查阅目前的一些按键内容呢?可以利用 stty (setting tty 终端机的意思) 呢! stty 也可以帮助配置终端机的输入按键代表意义喔!


^ 表示 [Ctrl] 那个按键的意思。举例来说, intr = ^C 表示利用 [ctrl] + c 来达成的。

几个重要的代表意义是:

    susp  : 送出一个 terminal stop 的讯号给正在 run 的程序。

stty <按键内容> <按键>

如果你想要用 [ctrl]+h 来进行字符的删除,那么可以下达:

    [root@www ~]# stty erase ^h

除了 stty 之外,其实我们的 bash 还有自己的一些终端机配置值呢!那就是利用 set 来配置的! 我们之前提到一些变量时,可以利用 set 来显示,除此之外,其实 set 还可以帮我们配置整个命令输出/输入的环境。 例如记录历史命令、显示错误内容等等


另外,其实我们还有其他的按键配置功能呢!就是在前一小节提到的 /etc/inputrc 这个文件里面配置。

bash 默认的组合键汇整如下:

    Ctrl + Z 『暂停』目前的命

5)通配符与特殊符号

常用的通配符喔:

    [^ ] 若中括号内的第一个字符为指数符号 (^) ,那表示『反向选择』,例如 [^abc] 代表 一定有一个字符,只要是非 a, b, c 的其他字符就接受的意思。

接下来让我们利用通配符来玩些东西吧!首先,利用通配符配合 ls 找檔名看看:


除了通配符之外,bash 环境中的特殊符号有哪些呢?底下我们先汇整一下:

    # 批注符号:这个最常被使用在 script 当中,视为说明!在后的数据均不运行

5.数据流重导向 (Redirection)

1)何谓数据流重导向?

数据流重导向就是将某个命令运行后应该要出现在屏幕上的数据, 给他传输到其他的地方,例如文件或者是装置 (例如打印机之类的)!

standard output 与 standard error output(『标准输出』与『标准错误输出』)

不管正确或错误的数据都是默认输出到屏幕上,所以屏幕当然是乱乱的!

那能不能透过某些机制将这两股数据分开呢? 当然可以啊!那就是数据流重导向的功能啊!数据流重导向可以将 standard output (简称 stdout) 与 standard error output (简称 stderr) 分别传送到其他的文件或装置去,而分别传送所用的特殊字符则如下所示:

    标准错误输出(stderr):代码为 2 ,使用 2> 或 2>> ;

为了理解 stdout 与 stderr ,我们先来进行一个范例的练习:


文件的创建方式是:

也就是若以 > 输出到一个已存在的文件中,那个文件就会被覆盖掉啰!使用>>不会被覆盖

/dev/null 垃圾桶黑洞装置与特殊写法

如果我知道错误信息会发生,所以要将错误信息忽略掉而不显示或储存呢? 这个时候黑洞装置 /dev/null 就很重要了!这个 /dev/null 可以吃掉任何导向这个装置的信息喔!


再想象一下,如果我要将正确与错误数据通通写入同一个文件去呢?这个时候就得要使用特殊的写法了! 


standard input : < 与 << 

那么那个 < 又是什么呀?呵呵!以最简单的说法来说, 那就是『将原本需要由键盘输入的数据,改由文件内容来取代』的意思。 


利用 << 右侧的控制字符,我们可以终止一次输入, 而不必输入 [crtl]+d 来结束哩!这对程序写作很有帮助喔!好了,那么为何要使用命令输出重导向呢?我们来说一说吧!

2)命令运行的判断依据: ; , &&, ||

在某些情况下,很多命令我想要一次输入去运行,而不想要分次运行时,该如何是好?基本上你有两个选择, 一个是透过第十三章要介绍的 shell script 撰写脚本去运行,一种则是透过底下的介绍来一次输入多重命令喔!

cmd ; cmd (cmd表示一个命令,不考虑命令相关性的连续命令下达)

例如在关机的时候我希望可以先运行两次 sync 同步化写入磁盘后才 shutdown 计算机,那么可以怎么作呢?这样做呀:

[root@www ~]# sync; sync; shutdown -h now

$? (命令回传值) 与 && 或 ||

两个命令彼此之间是有相关性的, 前一个命令是否成功的运行与后一个命令是否要运行有关!那就得动用到 && 或 || 啰!同时还要用到命令回传值『若前一个命令运行的结果为正确,在 Linux 底下会回传一个 $? = 0 的值』。

cmd1 && cmd2

    若 cmd1 运行完毕且正确运行($?=0),则开始运行 cmd2;错误 ($?≠0),则 cmd2 不运行。

cmd1 || cmd2

    若 cmd1 运行完毕且正确运行($?=0),则 cmd2 不运行;错误 ($?≠0),则开始运行 cmd2。

Linux 底下的命令都是由左往右运行。

6.管线命令 (pipe)

bash 命令运行的时候有输出的数据会出现! 那么如果这群数据必需要经过几道手续之后才能得到我们所想要的格式,应该如何来配置? 这就牵涉到管线命令的问题了 (pipe) ,管线命令使用的是『 | 』这个界定符号! 另外,管线命令与『连续下达命令』是不一样的呦!

管线命令『 | 』仅能处理经由前面一个命令传来的正确信息,也就是 standard output 的信息,对于 stdandard error 并没有直接处理的能力。

在每个管线后面接的第一个数据必定是『命令』喔!而且这个命令必须要能够接受 standard input 的数据才行。例如 less, more, head, tail 等都是可以接受 standard input 的管线命令啦。

1)撷取命令: cut, grep

数据经过分析后,取出我们所想要的。撷取信息通常是针对『一行一行』来分析的。

cut

cut 主要的用途在于将『同一行里面的数据进行分解!』不过,cut 在处理多空格相连的数据时,可能会比较吃力一点。


grep

grep 则是分析一行信息, 若当中有我们所需要的信息,就将该行拿出来


grep 可以解析一行文字,取得关键词,若该行有存在关键词,就会整行列出来!

2)排序命令: sort, uniq, wc

sort

sort 是很有趣的命令,他可以帮我们进行排序,而且可以依据不同的数据型态来排序喔! 例如数字与文字的排序就不一样。此外,排序的字符与语系的编码有关,因此, 如果您需要排序时,建议使用 LANG=C 来让语系统一,数据排序比较好一些。


uniq

如果我排序完成了,想要将重复的数据仅列出一个显示,可以怎么做呢?


上面的范例, (1)先将所有的数据列出;(2)再将人名独立出来;(3)经过排序;(4)只显示一个! 由于这个命令是在将重复的东西减少,所以当然需要『配合排序过的文件』来处理啰!

we

如果我想要知道 /etc/man.config 这个文件里面有多少字?多少行?多少字符的话, 可以怎么做呢?其实可以利用 wc 这个命令来达成喔!他可以帮我们计算输出的信息的整体数据!


3)双向重导向: tee

tee 会同时将数据流分送到文件去与屏幕 (screen);而输出到屏幕的,其实就是 stdout ,可以让下个命令继续处理喔!


tee 可以让 standard output 转存一份到文件内并将同样的数据继续送到屏幕去处理! 这样除了可以让我们同时分析一份数据并记录下来之外,还可以作为处理一份数据的中间缓存盘记录之用!

4)字符转换命令: tr, col, join, paste, expand

tr

tr 可以用来删除一段信息当中的文字,或者是进行文字信息的替换!


col


很多时候,他可以用来简单的处理将 [tab] 按键取代成为空格键!

此外, col 经常被利用于将 man page 转存为纯文本文件以方便查阅的功能!如上述的范例二!

join

join 看字面上的意义 (加入/参加) 就可以知道,他是在处理两个文件之间的数据, 而且,主要是在处理『两个文件当中,有 "相同数据" 的那一行,才将他加在一起』的意思。


paste

paste 就直接『将两行贴在一起,且中间以 [tab] 键隔开』而已!简单的使用方法:


expand

这玩意儿就是在将 [tab] 按键转成空格键啦~可以这样玩:


5)分割命令: split

可以帮你将一个大文件,依据文件大小或行数来分割,就可以将大文件分割成为小文件了! 快速又有效啊!


6)参数代换: xargs

xargs 是在做什么的呢?就以字面上的意义来看, x 是加减乘除的乘号,args 则是 arguments (参数) 的意思,所以说,这个玩意儿就是在产生某个命令的参数的意思! xargs 可以读入 stdin 的数据,并且以空格符或断行字符作为分辨,将 stdin 的数据分隔成为 arguments 。

 因为是以空格符作为分隔,所以,如果有一些档名或者是其他意义的名词内含有空格符的时候, xargs 可能就会误判了~


会使用 xargs 的原因是, 很多命令其实并不支持管线命令,因此我们可以透过 xargs 来提供该命令引用 standard input 之用!举例来说,我们使用如下的范例来说明:

7)关于减号 - 的用途

管线命令在 bash 的连续的处理程序中是相当重要的!另外,在 log file 的分析当中也是相当重要的一环, 所以请特别留意!另外,在管线命令当中,常常会使用到前一个命令的 stdout 作为这次的 stdin , 某些命令需要用到文件名 (例如 tar) 来进行处理时,该 stdin 与 stdout 可以利用减号 "-" 来替代

举例来说:

    [root@www ~]# tar -cvf - /home | tar -xvf -


转载自:http://cn.linux.vbird.org/linux_basic/linux_basic.php








猜你喜欢

转载自blog.csdn.net/badmushroom/article/details/79642764
今日推荐