鸟哥的 Linux 私房菜第11章-认识与学习 BASH 学习笔记

/bin/bash 是 Linux 预设的 shell


bash可以记忆使用过的指令

~/.bash_history 记录的是前一次登入以前所执行过的指令


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

连续按两次 [tab]列出所有提示


命令别名设定功能: (alias)

alias lm='ls -al'


工作控制、前景背景控制


程序化脚本: (shell scripts)


通配符: (Wildcard)


[root@www ~]# type [-tpa] name  #选项与参数: :不加任何选项与参数时,type 会显示出 name 是外部指令还是 bash 内建指令


指令的下达

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


『变量就是以一组文字或符号等,来取代一些设定或者是一串保留的数据!』

由于系统需要一些变量来提供他数据的存取 ,所以就有一些所谓的『环境变量』 需要来读入系统中了!

环境变量例如 PATH、HOME、MAIL、SHELL

环境变量通常以大写字符来表示

变量在被取用时,前面必须要加上钱字号『 $ 』才行


变数的取用: echo

[root@www ~]# echo $PATH


用『等号(=)』连接变量与他的内容『设定』或者是『修改』 某个变量的内容

变量的设定规则:

1. 变量与变量内容以一个等号『=』来连结

2. 等号两边不能直接接空格符

3. 变量名称只能是英文字母与数字,但是开头字符不能是数字

4. 变量内容若有空格符可使用双引号『"』或单引号『'』将变量内容结合起来,但双引号内的特殊字符如 $ 等,可以保有原本的特性;单引号内的特殊字符则仅为一般字符。

5. 可用跳脱字符『 \ 』将特殊符号(如 [Enter], $, \, 空格符, '等)变成一般字符;

6. 在一串指令中,还需要藉由其他的指令提供的信息,可以使用反单引号『`指令`』或 『$(指令)』

7. 若该变量为扩增变量内容时,则可用 "$变量名称" 或 ${变量} 累加内容,如下所示: 『PATH="$PATH":/home/bin』

8. 若该变量需要在其他子程序执行,则需要以 export 来使变量变成环境变量: 『export PATH』

9. 通常大写字符为系统默认变量,自行设定变量可以使用小写字符,方便判断 (纯粹依照使用者兴趣与嗜好) ;

10.取消变量的方法为使用 unset :『unset 变量名称』例如取消 myname 的设定: 『unset myname』


『子程序』:

就是说,在我目前这个 shell 的情况下,去启用另一个新的 shell ,新的那个 shell 就是子程序啦!

在一般的状态下,父程序的自定义变量是无法在子程序内使用的。但是透过 export 将变量变成环境变量后,就能够在子程序底下应用了!


范例:如何进入到您目前核心的模块目录?

[root@www ~]# cd /lib/modules/`uname -r`/kernel

利用 uname -r 这个指令取得版本信息。


范例一:列出目前的 shell 环境下的所有环境变量与其内容。

[root@www ~]# env

PS1='[\u@\h \W]\$ ' <== PS1 就厉害了。这个是命令提示字符,也就是我们常见的 [root@www ~]# 或 [dmtsai ~]$ 的设定值啦!可以更动的!

$ <== 目前这个 shell 所使用的 PID

? <== 刚刚执行完指令的回传值。


将自定义变量变成环境变量

[root@www ~]# export 变量名称


[root@www ~]# locale

[root@www ~]# cat /etc/sysconfig/i18n


read命令

[root@www ~]# read atest This is a test <==此时光标会等待你输入!


declare / typeset 是一样的功能,宣告变量的类型

[root@www ~]# declare -i sum=100+300+50


数组 (array) 变量类型

var[index]=content

[root@www ~]# var[1]="small min"

[root@www ~]# var[2]="big min"

[root@www ~]# var[3]="nice min"

[root@www ~]# echo "${var[1]}, ${var[2]}, ${var[3]}"


限制用户的某些系统资源: ulimit

[root@www ~]# ulimit [-SHacdfltu] [配额]


变量内容的删除与取代:

『从前面开始删除变量内容』:

[root@www ~]# path=${PATH}

[root@www ~]# echo ${path#/*kerberos/bin:}   #要将/usr/kerberos/sbin:/usr/kerberos/bin:两个目录删除掉 

[root@www ~]# echo ${path##/*:}  #从头删除掉目录就是介于斜线 (/) 到冒号 (:) 之间的数据

# :符合取代文字的『最短的』那一个;

##:符合取代文字的『最长的』那一个


『从后面向前删除变量内容』:

[root@www ~]# echo ${path%:*bin}

# :符合取代文字的『最短的』那一个;

##:符合取代文字的『最长的』那一个


『取代』:

[root@www ~]# echo ${path/sbin/SBIN}  #将 path 的变量内容内的第一个 sbin 取代成大写 SBIN

[root@www ~]# echo ${path//sbin/SBIN}  #将 path 的变量内容内的所有的sbin 取代成大写 SBIN


[root@www ~]# username="vbird tsai"

[root@www ~]# username=${username-root}   #因为 username 已经设定了(为空),所以使用旧有的设定而不以 root 取代

[root@www ~]# username=${username:-root}  #加上『 : 』后若变量内容为空或者是未设定,都能够以后面的内容替换!


如果你想要将旧变量内容也一起替换掉的话,那么就使用等号 (=) 吧:

[root@www ~]# unset str; var=${str=newvar}


如果旧变量不存在时,整个测试就告知我『有错误』,此时就能够使用问号『 ? 』

[root@www ~]# unset str; var=${str?无此变量}

-bash: str: 无此变量


命令别名设定: alias, unalias:

[root@www ~]# alias lm='ls -l | more'    #立刻多出了一个可以执行的指令喔!这个指令名称为 lm

[root@www ~]# alias rm='rm -i'    #命令别名的设定还可以取代既有的指令

目前有哪些的命令别名:

[root@www ~]# alias


取消命令别名unalias:

[root@www ~]# unalias lm


历史命令:history (查询我们曾经下达过的指令)

[root@www ~]# !number

[root@www ~]# !command

[root@www ~]# !!

参数: number :执行第几笔指令的意思; command :由最近的指令向前搜寻『指令串开头为 command』的那个指令,并执行; !! :就是执行上一个指令(相当于按↑按键后,按 Enter)


bash 的进站与欢迎讯息: /etc/issue, /etc/motd

除了 /etc/issue 之外还有个 /etc/issue.net 呢!这是啥?这个是提供给 telnet 这个远程登录程序用的


login shell:

其实只会读取这两个配置文件:
1. /etc/profile:这是系统整体的设定,你最好不要修改这个档案;
2. ~/.bash_profile 或 ~/.bash_login 或 ~/.profile:属于使用者个人设定,你要改自己的数据,就写入这里!

在 CentOS 5.x 默认的情况下, 底下这些数据会依序的被呼叫进来:

/etc/inputrc   #此一档案内容为 bash 的热键啦、[tab]要不要有声音啦等等的数据!

/etc/profile.d/*.sh  #这个目录底下的档案规范了 bash 操作接口的颜色、 语系、ll 与 ls 指令的命令别名、vi 的命令别名、which 的命令别名等等

/etc/sysconfig/i18n   #由 /etc/profile.d/lang.sh 呼叫进来的!决定 bash 预设使用何种语系的重要配置文件! 最重要的就是 LANG 这个变量啦!

~/.bash_profile 

~/.bash_login

~/.profile

如果 ~/.bash_profile 不存在才会去读取 ~/.bash_login,而前两者都不存在才会读取 ~/.profile


[root@www ~]# cat ~/.bash_profile

# .bash_profile

# Get the aliases and functions

if [ -f ~/.bashrc ]; then <==底下这三行在判断并读取 ~/.bashrc

    . ~/.bashrc

fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin <==底下这几行在处理个人化设定

export PATH

unset USERNAME


source

[root@www ~]# source 配置文件档名

[root@www ~]# source ~/.bashrc    <==底下这两个指令是一样的!

[root@www ~]# . ~/.bashrc

利用 source 或小数点 (.) 都可以将配置文件的内容读进来目前的 shell 环境中!


non-login shell:

~/.bashrc

[root@www ~]# cat ~/.bashrc

# .bashrc

# User specific aliases and functions

alias rm='rm -i' <==使用者的个人设定

alias cp='cp -i'

alias mv='mv -i'

# Source global definitions

if [ -f /etc/bashrc ]; then <==整体的环境设定

    . /etc/bashrc

fi


其他配置文件

/etc/man.config

这个档案规定了下达 man 的时候,该去哪里查看数据的路径设定!


~/.bash_history

历史命令就记录在这里


~/.bash_logout

这个档案则记录了『当我注销 bash 后,系统再帮我做完什么动作后才离开』的意思。


终端机的环境设定: stty, set

[root@www ~]# stty -a  #列出所有的按键与按键内容

^ 表示 [Ctrl]

除了 stty 之外,其实我们的 bash 还有自己的一些终端机设定值呢!那就是利用 set 来设定的!

[root@www ~]# set [-uvCHhmBx]

选项与参数: -u :预设不启用。若启用后,当使用未设定变量时,会显示错误讯息; -v :预设不启用。若启用后,在讯息被输出前,会先显示讯息的原始内容; -x :预设不启用。若启用后,在指令被执行前,会显示指令内容(前面有 ++ 符号) -h :预设启用。与历史命令有关; -H :预设启用。与历史命令有关; -m :预设启用。与工作管理有关; -B :预设启用。与刮号 [] 的作用有关; -C :预设不启用。若使用 > 等,则若档案存在时,该档案不会被覆盖。

其实我们还有其他的按键设定功能呢!就是在前一小节提到的 /etc/inputrc 这个档案里面设定


通配符

* 代表『 0 个到无穷多个』任意字符

? 代表『一定有一个』任意字符

[ ] 同样代表『一定有一个在括号内』的字符(非任意字符)。例如 [abcd] 代表『一定有一个字符, 可能是 a, b, c, d 这四个任何一个』

[ - ] 若有减号在中括号内时,代表『在编码顺序内的所有字符』。例如 [0-9] 代表 0 到 9 之间的所有数字,因为数字的语系编码是连续的!

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


bash 环境中的特殊符号

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

\ 跳脱符号:将『特殊字符或通配符』还原成一般字符

| 管线 (pipe):分隔两个管线命令的界定(后两节介绍);

; 连续指令下达分隔符:连续性命令的界定 (注意!与管线命令并不相同)

~ 用户的家目录

$ 取用变数前导符:亦即是变量之前需要加的变量取代值

& 工作控制 (job control):将指令变成背景下工作

! 逻辑运算意义上的『非』 not 的意思!

/ 目录符号:路径分隔的符号

>, >> 数据流重导向:输出导向,分别是『取代』与『累加』

<, << 数据流重导向:输入导向

' ' 单引号,不具有变量置换的功能

" " 具有变量置换的功能!

` ` 两个『 ` 』中间为可以先执行的指令,亦可使用 $( )

( ) 在中间为子 shell 的起始与结束

{ } 在中间为命令区块的组合!


数据流重导向

1>、1>>、2>、2>>

数据流重导向就是将某个指令执行后应该要出现在屏幕上的数据, 给他传输到其他的地方。

[root@www ~]# ll / > ~/rootfile    #观察你的系统根目录 (/) 下各目录的文件名、权限与属性,并记录下来

[dmtsai@www ~]$ find /home -name .bashrc > list_right 2> list_error  #将 stdout 与 stderr 分存到不同的档案去


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

[dmtsai@www ~]$ find /home -name .bashrc 2> /dev/null    #将错误讯息忽略掉而不显示或储存


#将指令的数据全部写入名为 list 的档案中,以下两种写法都正确:

[dmtsai@www ~]$ find /home -name .bashrc > list 2>&1  

[dmtsai@www ~]$ find /home -name .bashrc &> list


standard input : < 与 <<

将原本需要由键盘输入的数据,改由档案内容来取代

[root@www ~]# cat > catfile   #利用 cat 指令来建立一个档案的简单流程

testing cat file test

<==这里按下 [ctrl]+d 来离开

[root@www ~]# cat > catfile < ~/.bashrc   #这两个档案的大小会一模一样!几乎像是使用 cp 来复制一般!

<<    代表的是『结束的输入字符』

例如:[root@www ~]# cat > catfile << "eof"    # 输入这关键词,立刻就结束而不需要输入 [ctrl]+d


cmd ; cmd (不考虑指令相关性的连续指令下达)

[root@www ~]# sync; sync; shutdown -h now  #在关机的时候我希望可以先执行两次 sync 同步化写入磁盘后才 shutdown 计算机


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

cmd1 && cmd2 1. 若 cmd1 执行完毕且正确执行($?=0),则开始执行 cmd2。 2. 若 cmd1 执行完毕且为错误 ($?≠0),则 cmd2 不执行。

cmd1 || cmd2 1. 若 cmd1 执行完毕且正确执行($?=0),则 cmd2 不执行。 2. 若 cmd1 执行完毕且为错误 ($?≠0),则开始执行 cmd2。


管线命令 (pipe)

每个管线后面接的第一个数据必定是『指令』喔!而且这个指令必须要能够接受 standard input 的数据才行,这样的指令才可以是为『管线命令』

[root@www ~]# ls -al /etc | less


撷取命令: cut, grep

cut 主要的用途在于将『同一行里面的数据进行分解!』最常使用在分析一些数据或文字数据的时候!

[root@www ~]# echo $PATH | cut -d ':' -f 5   #将 PATH 变量取出,我要找出第五个路径。

[root@www ~]# echo $PATH | cut -d ':' -f 3,5   #要列出第 3 与第 5 呢

[root@www ~]# export | cut -c 12-  # 取得第 12 字符以后的所有字符串

# 我们还可以指定某个范围的值,例如第 12-20 的字符,就是 cut -c 12-20 等等

[root@www ~]# last | cut -d ' ' -f 1  #用 last 将显示的登入者的信息中,仅留下用户大名

cut 在处理多空格相连的数据时,可能会比较吃力一点。


grep

[root@www ~]# grep [-acinv] [--color=auto] '搜寻字符串' filename

选项与参数: -a :将 binary 档案以 text 档案的方式搜寻数据 -c :计算找到 '搜寻字符串' 的次数 -i :忽略大小写的不同,所以大小写视为相同 -n :顺便输出行号 -v :反向选择,亦即显示出没有 '搜寻字符串' 内容的那一行! --color=auto :可以将找到的关键词部分加上颜色的显示喔!

[root@www ~]# last | grep 'root'

[root@www ~]# last | grep -v 'root'

[root@www ~]# last | grep 'root' |cut -d ' ' -f1


排序命令: sort, wc, uniq

sort

[root@www ~]# sort [-fbMnrtuk] [file or stdin]

选项与参数: -f :忽略大小写的差异,例如 A 与 a 视为编码相同; -b :忽略最前面的空格符部分; -M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法; -n :使用『纯数字』进行排序(默认是以文字型态来排序的); -r :反向排序; -u :就是 uniq ,相同的数据中,仅出现一行代表; -t :分隔符,预设是用 [tab] 键来分隔; -k :以那个区间 (field) 来进行排序的意思

[root@www ~]# cat /etc/passwd | sort

[root@www ~]# cat /etc/passwd | sort -t ':' -k 3  #/etc/passwd 内容是以 : 来分隔的,我想以第三栏来排序

[root@www ~]# last | cut -d ' ' -f1 | sort  #利用 last ,将输出的数据仅取账号,并加以排序


uniq

[root@www ~]# uniq [-ic]

选项与参数: -i :忽略大小写字符的不同; -c :进行计数

[root@www ~]# last | cut -d ' ' -f1 | sort | uniq   #使用 last 将账号列出,仅取出账号栏,进行排序后仅取出一位;

[root@www ~]# last | cut -d ' ' -f1 | sort | uniq -c  #承上题,如果我还想要知道每个人的登入总次数


wc

[root@www ~]# wc [-lwm]

选项与参数: -l :仅列出行; -w :仅列出多少字(英文单字); -m :多少字符;

[root@www ~]# cat /etc/man.config | wc  # 输出的三个数字中,分别代表: 『行、字数、字符数』

[root@www ~]# last | grep [a-zA-Z] | grep -v 'wtmp' | wc -l


tee

[root@www ~]# tee [-a] file

选项与参数: -a :以累加 (append) 的方式,将数据加入 file 当中!

[root@www ~]# last | tee last.list | cut -d " " -f1  # 这个范例可以让我们将 last 的输出存一份到 last.list 档案中

[root@www ~]# ls -l / | tee -a ~/homefile | more   # 要注意! tee 后接的档案会被覆盖,若加上 -a 这个选项则能将讯息累加。


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

tr 

[root@www ~]# tr [-ds] SET1 ...

选项与参数: -d :删除讯息当中的 SET1 这个字符串; -s :取代掉重复的字符!

[root@www ~]# last | tr '[a-z]' '[A-Z]'  #将 last 输出的讯息中,所有的小写变成大写字符

[root@www ~]# cat /etc/passwd | tr -d ':'   #将 /etc/passwd 输出的讯息中,将冒号 (:) 删除

范例三:将 /etc/passwd 转存成 dos 断行到 /root/passwd 中,再将 ^M 符号删除

[root@www ~]# cp /etc/passwd /root/passwd && unix2dos /root/passwd

[root@www ~]# file /etc/passwd /root/passwd

[root@www ~]# cat /root/passwd | tr -d '\r' > /root/passwd.linux


col

[root@www ~]# col [-xb]

选项与参数: -x :将 tab 键转换成对等的空格键 -b :在文字内有反斜杠 (/) 时,仅保留反斜杠最后接的那个字符

[root@www ~]# cat /etc/man.config | col -x | cat -A | more  #[tab] 按键会被取代成为空格键

[root@www ~]# man col > /root/col.man  #将 col 的 man page 转存成为 /root/col.man 的纯文本档


join

主要是在处理『两个档案当中,有 "相同数据" 的那一行,才将他加在一起』

[root@www ~]# join [-ti12] file1 file2

选项与参数: -t :join 默认以空格符分隔数据,并且比对『第一个字段』的数据, 如果两个档案相同,则将两笔数据联成一行,且第一个字段放在第一个! -i :忽略大小写的差异; -1 :这个是数字的 1 ,代表『第一个档案要用那个字段来分析』的意思; -2 :代表『第二个档案要用那个字段来分析』的意思。

[root@www ~]# join -t ':' /etc/passwd /etc/shadow  #用 root 的身份,将 /etc/passwd 与 /etc/shadow 相关数据整合成一栏

[root@www ~]# join -t ':' -1 4 /etc/passwd -2 3 /etc/group    #我们知道 /etc/passwd 第四个字段是 GID ,那个 GID 记录在 /etc/group 当中的第三个字段,将两个档案整合

需要特别注意的是,在使用 join 之前,你所需要处理的档案应该要事先经过排序 (sort) 处理!


paste

直接『将两行贴在一起,且中间以 [tab] 键隔开』而已

[root@www ~]# paste [-d] file1 file2

选项与参数: -d :后面可以接分隔字符。预设是以 [tab] 来分隔的!
- :如果 file 部分写成 - ,表示来自 standard input 的资料的意思.

[root@www ~]# paste /etc/passwd /etc/shadow  #将 /etc/passwd 与 /etc/shadow 同一行贴在一起

[root@www ~]# cat /etc/group|paste /etc/passwd /etc/shadow -|head -n 3  #先将 /etc/group 读出(用 cat),然后与范例一贴上一起!且仅取出前三行


expand

这玩意儿就是在将 [tab] 按键转成空格键啦

[root@www ~]# expand [-t] file

选项与参数: -t :后面可以接数字。一般来说,一个 tab 按键可以用 8 个空格键取代。

[root@www ~]# grep '^MANPATH' /etc/man.config | head -n 3 |  expand -t 6 - | cat -A


分割命令: split

他可以帮你将一个大档案,依据档案大小或行数来分割,就可以将大档案分割成为小档案了!

[root@www ~]# split [-bl] file PREFIX

选项与参数: -b :后面可接欲分割成的档案大小,可加单位,例如 b, k,
m 等; -l :以行数来进行分割。 PREFIX :代表前导符的意思,可作为分割档案的前导文字.

[root@www tmp]# cat termcap* >> termcapback  #将上面的三个小档案合成一个档案,档名为 termcapback

[root@www tmp]# ls -al / | split -l 10 - lsroot   #使用 ls -al / 输出的信息中,每十行记录成一个档案


参数代换: xargs

[root@www ~]# xargs [-0epn] command

参数: -0 :如果输入的 stdin 含有特殊字符,例如 `, \, 空格键等等字符时,这个 -0 参数 可以将他还原成一般字符。这个参数可以用于特殊状态喔! -e :这个是 EOF (end of file) 的意思。后面可以接一个字符串,当 xargs 分析到 这个字符串时,就会停止继续工作! -p :在执行每个指令的 argument 时,都会询问使用者的意思; -n :后面接次数,每次 command 指令执行时,要使用几个参数的意思。看范例三。 当 xargs 后面没有接任何的指令时,默认是以 echo 来进行输出喔!

[root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs finger   #将 /etc/passwd 内的第一栏取出,仅取三行,使用 finger 这个指令将每个 账号内容秀出来

[root@www ~]# cut -d':' -f1 /etc/passwd |head -n 3| xargs -p finger  #同上,但是每次执行 finger 时,都要询问使用者是否动作?

[root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -n 5 finger  #将所有的 /etc/passwd 内的账号都以 finger 查阅,但一次仅查阅五个账号

[root@www ~]# cut -d':' -f1 /etc/passwd | xargs -p -e'lp' finger  #同上,但是当分析到 lp 就结束这串指令

会使用 xargs 的原因是, 很多指令其实并不支持管线命令,因此我们可以透过 xargs 来提供该指令引用 standard input 之用

错误示范:[root@www ~]# find /sbin -perm +7000 | ls -l   #找出 /sbin 底下具有特殊权限的档名,并使用 ls -l 列出详细属性(因为 ll (ls) 并不是管线命令的原因)

正确示范:[root@www ~]# find /sbin -perm +7000 | xargs ls -l   #找出 /sbin 底下具有特殊权限的档名,并使用 ls -l 列出详细属性


关于减号 - 的用途

在管线命令当中,常常会使用到前一个指令的 stdout 作为这次的 stdin,某些指令需要用到文件名 (例如 tar) 来进行处理时,该 stdin 与 stdout 可以利用减号 "-" 来替代

[root@www ~]# tar -cvf - /home | tar -xvf -     #『我将 /home 里面的档案给他打包,但打包的数据不是纪录到档案,而是传送到 stdout; 经过管线后,将 tar -cvf - /home 传送给后面的 tar -xvf - 』。后面的这个 - 则是取用前一个指令的 stdout, 因此,我们就不需要使用 file 了




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值