bash特性知多少

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rdgfdd/article/details/82194458

此文是对于centos系统中bash特性的较为详尽的介绍。

bash基础特性1:命令历史

命令历史:

shell进程会在其会话中保存此前用户提交、执行过的命令,称之为“命令历史”;

那么,如何来查看命令历史呢?


history : 查看历史命令(内存中的所有历史命令)


用法

    history  [-c] [-d offest] [n] 
    history  -anrw  [文件名]
    history  -ps 参数 [参数....]

定制·history·的功能可通过环境变量来实现,有以下两种:

  • HISTSIZE :

    shell进程可保留的历史命令的条数

  • HISTFILE :

    持久保存命令历史的文件,文件名为 .bash_history 。在当前shell中输入的命令历史,直接保存在内存中,当shell退出时将此shell中的命令历史保存到文件.bash_history中。

  • HISTFILESIZE :

    HISTFILE文件的大小,当命令历史条数大于这个值,将会把旧命令踢出、新的历史命令写入HISTFILE;

示例:

[root@localhost jeffrey]# history
    1  ls
    2  sudo apt install yum
    3  yum install tree
    4  tree
    5  yum install tree
    6  tree
    7  ls
    .......
  104  who -r
  105  w
  106  histtory
  107  history

选项:

    -c :   清空命令历史
    -d offest :   删除指定位置的命令历史
    -d offest n :   删除从指定位置开始的n条命令
    -w :   将内存中的命令历史保存到文件(HISTFILE)中
    -r :   将文件(HISTFILE)中的命令历史读取到内存中
    history # :   显示最近的#条命令   

示例:

[root@localhost jeffrey]# history -c
[root@localhost jeffrey]# history
    1  history

[root@localhost jeffrey]# history -r
[root@localhost jeffrey]# history
    1  history
    2  cat HISTFILE
    3  history -r
    4  ls
    5  sudo apt install yum
    6  yum install tree
    7  tree
    .......
   98  which mv
   99  which --skip-alias rm
  100  which --skip-alias mv
  101  reboot
  102  history

[root@localhost jeffrey]# cat .bash_history
ls
cd Document
ls
cd Documents
ls
tree
sudo install tree
sudo apt install yum
su
type
type ls


[root@localhost jeffrey]# history -w .bash_history
[root@localhost jeffrey]# cat .bash_history
history
cat HISTFILE
history -r
ls
sudo apt install yum
yum install tree
tree
.......
cat .bash_history
echo $HISTSIZE
echo $HISTFILESIZE
cat .bash_history
history -w
cat .bash_history
history
cat .bash_history
history -w .bash_history

那么,该如何调用命令历史列表中的历史呢?


! n : 执行历史列表中的第n条命令
! ! : 指向上一条命令;更简单的是“向上方向键”
!STRING : 执行命令历史列表中最近一次以字符串’ STRING ‘开头的命令


示例:由于·ls·命令是我们上一条执行的命令,所以·!l·匹配到的最近的以l开头的命令就是ls.

[root@localhost jeffrey]# ls
Desktop  Documents  Downloads  Music  Pictures  Public  
Templates  Videos
[root@localhost jeffrey]# man useradd
[root@localhost jeffrey]# !l
ls
Desktop  Documents  Downloads  Music  Pictures  Public  
Templates  Videos

:命令的重复执行有时候需要依赖于幂等性;

那么,到底什么是幂等性呢?

示例:

[root@localhost jeffrey]# mkdir mybook
[root@localhost jeffrey]# !m
mkdir mybook

由于,我们执行’ mkdir mybook ‘后,目录’ mybook ’ 已经创建了,所以,再一次执行该命令就会提示错误;所以,该命令的重复执行不具有幂等性!

下面,介绍一下如何调用上一条命令的最后一个参数。


Esc , . : 先按下Esc,然后松开,再按下 . 即可
!$ : 同时按住 !和 $


如何控制命令历史记录的方式呢?

答案是:通过环境变量“HISTCONTROL”


HISTCONTORL=ignoredups : 忽略重复(相同且连续)的命令
HISTCONTORL=ignorespace : 忽略以空白字符开头的命令
HISTCONTORL=ignoreboth : 以上两者同时生效

示例:

[root@localhost mybook]# HISTCONTORL=ignoredups  
[root@localhost mybook]# HISTCONTORL=ignorespace
[root@localhost mybook]# HISTCONTORL=ignoreboth

可用以下方式来修改变量的值:


 NAME='VALUE'

bash基础特性2:命令补全和路径补全


  • 命令查找:

    shell程序在接收到用户执行命令的请求,分析完成之后,最左侧的字符串会被当做命令;然后执行命令查找机制:
    (1)在shell内部命令中查找与命令名相同的文件,并执行、发起 一个进程
    (2)若未找到,则根据PATH环境变量中设定的目录,自左而右逐个搜索目录下的文件名,然后发起一个进程;

  • 命令补全:

    首先,在命令行给出一个待补全字符串,按下Tab键:
    (1)若待补全字符串能唯一标识某个命令程序文件,则会直接补全;
    (2)若不能唯一标识,此时,再按一次Tab键则会显示所有可能命令的列表

示例:输入’ mkdi ‘进行匹配,按一下Tab键无法补全,所以,再按一次Tab键,便出现所有可能命令的列表

[root@localhost mybook]# mkdi
mkdict  mkdir   
  • 路径补全:

    在给定的起始路径下,以对应路径下的打头字符串来逐一匹配起始路径下的每个文件。
    若能唯一标识,则直接补全路径;
    否则,再敲一次Tab,会给出所有可能的列表;

示例:

[root@localhost jeffrey]# cd D
Desktop/   Documents/ Downloads/ 

bash基础特性3:命令行展开

~ : 自动展开为用户的家目录,或指定的家目录
{} : 可承载一个以逗号分隔的路径列表,并能将其展开为多个路径;

示例:

~ : 自动展开为用户的家目录 或 指定用户的家目录;

[root@localhost jeffrey]# echo ~
/root

{ } : 可承载一个以逗号分隔的路径列表,并能将其展开为多个路径 ;

[root@localhost jeffrey]# mkdir -pv /work/hardwares/x/{y1,y2}
mkdir: created directory ‘/work’
mkdir: created directory ‘/work/hardwares’
mkdir: created directory ‘/work/hardwares/xmkdir: created directory ‘/work/hardwares/x/y1’
mkdir: created directory ‘/work/hardwares/x/y2’

[root@localhost jeffrey]# tree /work
/work
`-- hardwares
    `-- x
        |-- y1
        `-- y2

4 directories, 0 files

这里我们查看命令行展开,使用了tree命令


tree : 显示完整目录树


用法:

   tree  [options]  [directory]

选项:

    -L level :   指定要要显示的层级

以下做几个练习题:

(1) 创建/mybook目录下的:a_c, a_d, b_c, b_d

[root@localhost /]# mkdir -pv /mybook/{a,b}_{c,d}
mkdir: created directory ‘/mybook/a_c’
mkdir: created directory ‘/mybook/a_d’
mkdir: created directory ‘/mybook/b_c’
mkdir: created directory ‘/mybook/b_d’
[root@localhost /]# tree mybook
mybook
|-- a_c
|-- a_d
|-- b_c
`-- b_d

4 directories, 0 files

(2) 创建/tmp/mylinux目录下的:
mylinux/
├── bin
├── boot
│ └── grub
├── dev
├── etc
│ ├── rc.d
│ │ └── init.d
│ └── sysconfig
│ └── network-scripts
├── lib
│ └── modules
├── lib64
├── proc
├── sbin
├── sys
├── tmp
├── usr
│ └── local
│ ├── bin
│ └── sbin
└── var
├── lock
├── log
└── run

[root@localhost /]# mkdir -pv /work/mylinux/{bin,boot/grub,dev,
etc/{rc.d/init.d,sysconfig/network_scripts},lib/modules,lib64,proc,
sbin,sys,tmp,usr/local/{bin,sbin},var/{lock,log,run}}
mkdir: created directory ‘/work/mylinux’
mkdir: created directory ‘/work/mylinux/bin’
mkdir: created directory ‘/work/mylinux/boot’
mkdir: created directory ‘/work/mylinux/boot/grub’
mkdir: created directory ‘/work/mylinux/dev’
mkdir: created directory ‘/work/mylinux/etc’
mkdir: created directory ‘/work/mylinux/etc/rc.d’
mkdir: created directory ‘/work/mylinux/etc/rc.d/init.d’
mkdir: created directory ‘/work/mylinux/etc/sysconfig’
mkdir: created directory ‘/work/mylinux/etc/sysconfig/network_scripts’
mkdir: created directory ‘/work/mylinux/lib’
mkdir: created directory ‘/work/mylinux/lib/modules’
mkdir: created directory ‘/work/mylinux/lib64’
mkdir: created directory ‘/work/mylinux/proc’
mkdir: created directory ‘/work/mylinux/sbin’
mkdir: created directory ‘/work/mylinux/sys’
mkdir: created directory ‘/work/mylinux/tmp’
mkdir: created directory ‘/work/mylinux/usr’
mkdir: created directory ‘/work/mylinux/usr/localmkdir: created directory ‘/work/mylinux/usr/local/bin’
mkdir: created directory ‘/work/mylinux/usr/local/sbin’
mkdir: created directory ‘/work/mylinux/var’
mkdir: created directory ‘/work/mylinux/var/lock’
mkdir: created directory ‘/work/mylinux/var/logmkdir: created directory ‘/work/mylinux/var/run’

[root@localhost /]# tree /work
/work
|-- hardwares
|   `-- x
|       |-- y1
|       `-- y2
`-- mylinux
    |-- bin
    |-- boot
    |   `-- grub
    |-- dev
    |-- etc
    |   |-- rc.d
    |   |   `-- init.d
    |   `-- sysconfig
    |       `-- network_scripts
    |-- lib
    |   `-- modules
    |-- lib64
    |-- proc
    |-- sbin
    |-- sys
    |-- tmp
    |-- usr
    |   `-- local
    |       |-- bin
    |       `-- sbin
    `-- var
        |-- lock
        |-- log
        `-- run

29 directories, 0 files

bash基础特性4:命令的执行状态结果

(1)bash通过状态返回值反映命令执行结果;此结果保存在bash中的特殊变量 $? 中。

若命令执行成功,返回值为0;若失败,返回值为1-255;

示例:

[root@hac-cent-jef jeffrey]# pwd
/home/jeffrey
[root@hac-cent-jef jeffrey]# echo $?
0

[root@hac-cent-jef jeffrey]# lss
bash: lss: command not found...
Similar command is: 'ls'
[root@hac-cent-jef jeffrey]# echo $?
127

2)若要引用命令的执行结果:$(COMMAND)或 `COMMAND`(反引号)

例:以hello为名称,创建一个文件夹
[root@hac-cent-jef jeffrey]# mkdir $(echo 'hello')
[root@hac-cent-jef jeffrey]# ls
Documents  hello  Music  var  Videos  Work  yang_2.c  yang.c

bash基础特性5:引用


单引号 ‘ ’ : 表示强引用
双引号 ” ” : 表示弱引用
反引号 : 表示命令引用


bash基础特性6:快捷键


Ctrl+a : 跳转到命令行首
Ctrl+e : 跳转到命令行尾
Ctrl+u : 删除命令行首到光标之间的字符
Ctrl+k : 删除光标到行尾之间的字符
Ctrl+l : 清屏,相当于clear


bash基础特性7:globbing 文件名通配


匹配模式:元字符

元字符主要包括:

* : 匹配任意长度的任意字符
? : 匹配任意单个字符
[ ] : 匹配指定范围内的单个字符
[^] : 匹配指定范围外的单个字符

其中,元字符 [ ] 和 [^] 的使用有几种特别形式 :

[a-z] : 匹配一个大写或小写字母,等价于[A-Z]
[0-9] : 匹配一个数字
[a-z0-9] : 匹配一个字母或数字
[abcxyz] : 匹配字符串abcxyz中的一个字母
2[0-9][0-9] :匹配200-299之间的数字
[[:upper:]] : 匹配一个大写字母
[[:lower:]] : 匹配一个小写字母
[[:alpha:]] : 匹配某个大写或小写字母
[[:digit:]] : 匹配一个数字
[[:alnum:]] : 匹配一个字母或数字,等价于:[[:alpha:][:digit:]]
[[:space:]] : 匹配一个空白字符
[[:punct:]] : 匹配一个标点符号
[^0-9] : 匹配一个非数字字符
[^[:upper:]] : 匹配一个非大写字母的字符

熟悉了上面的元字符,下面我们趁热打铁,来做几道练习题吧!

1,显示/var目录下所有以1开头、以一个小写字母结尾、且中间出现一位任意字符的文件或目录

[root@hac-cent-jef ~]# ls -d /var/1*[[:lower:]]
/var/1love

2,显示/etc目录下,以任一个数字开头,且以非数字结尾的文件或目录

[root@hac-cent-jef ~]# ls -d /etc/[0-9]*[^0-9]
/etc/1kshdlv  /etc/34jkbvrl  /etc/4t5d

3,显示/etc目录下,以非字母开头,后面跟一个字母及其他任意长度字符的文件或目录

[root@hac-cent-jef ~]# ls -d /etc/[^a-z][a-z]*
/etc/1kshdlv  /etc/4t5d

4,复制/etc目录下,所有以m开头的、以非数字结尾的文件或目录至/tmp/mybook中

[root@hac-cent-jef ~]# cp -r /etc/m*[^0-9] /tmp/mybook
[root@hac-cent-jef ~]# ls /tmp/mybook
machine-id  mail.rc                   maven        modprobe.d      mtab         my.cnf
magic       makedumpfile.conf.sample  mime.types   modules-load.d  mtools.conf  my.cnf.d
mailcap     man_db.conf               mke2fs.conf  motd            multipath

5,复制/usr/share/man目录下,所有以man开头、后跟一个数字结尾的文件或目录至/tmp/man目录下

[root@hac-cent-jef ~]# cp -r /usr/share/man/man*[0-9] /tmp/man
[root@hac-cent-jef ~]# ls /tmp/man
man1  man2  man3  man4  man5  man6  man7  man8  man9

6,复制/etc目录下,所有以.conf结尾,且以m,n,r,p开头的文件或目录至/tmp/conf.d

[root@hac-cent-jef ~]# cp -r /etc/[mnrp]*.conf /tmp/conf.d
[root@hac-cent-jef ~]# ls /tmp/conf.d
man_db.conf  mtools.conf  nfsmount.conf  ntp.conf      pnm2ppa.conf      resolv.conf  rsyslog.conf
mke2fs.conf  nfs.conf     nsswitch.conf  pbm2ppa.conf  request-key.conf  rsyncd.conf

bash基础特性8:I/O重定向及管道


程序=指令+数据
可用于输入的设备、文件有:键盘、文件系统的常规文件、网卡等
可用于输出的设备、文件有:显示器、文件系统的常规文件、网卡等

程序的数据流有三种:

输入的数据流 <————标准输入(stdin) 键盘
输出的数据流 ————>标准输出(stdout) 显示器
错误输出流 ————>错误输出(stderr)显示器

每一种数据流都有其文件描述符fd(即file descriptor):

标准输入 : 0
标准输出 : 1
错误输出 : 2

下面重点介绍:I/O重定向

  • 输出重定向 : >

    特点:覆盖输出

  • 输出重写向: >>

    特点:追加输出

  • set -c

    禁止输出重定向覆盖已存在的文件

  • set +c

    取消上述禁止的功能

  • 强制覆盖 : >|

  • 错误输出流重定向 : 2>

    特点:覆盖输出

  • 错误输出流重写向 : 2>>

    特点:追加输出

那么,如果想让正常输出流和错误输出流重定向到同一个文件当中呢?

可以合并正常输出流和错误输出流:

  • 重定向: &>
  • 重写向 : &>>

或者使用以下方式:

  • COMMAND > /path/to/somefile 2>&1
  • COMMAND >> /path/to/somefile 2>&1

示例:
(1),输出重定向

[root@hac-cent-jef ~]# ls
811.c  812.c  anaconda-ks.cfg  initial-setup-ks.cfg
[root@hac-cent-jef ~]# ls > document
[root@hac-cent-jef ~]# cat document
811.c
812.c
anaconda-ks.cfg
document
initial-setup-ks.cfg

(2)输出重写向

[root@hac-cent-jef ~]# echo 'hello world'
hello world
[root@hac-cent-jef ~]# echo 'hello world' >> document
[root@hac-cent-jef ~]# cat document
811.c
812.c
anaconda-ks.cfg
document
initial-setup-ks.cfg
hello world

对于I/O重定向,还有一个非常特殊的设备:/dev/null,我们称之为“数据黑洞”。这是因为所有输入到/dev/null中的数据都会被吞噬!

示例:将ls命令的结果输出重定向到数据黑洞/dev/null中

[root@hac-cent-jef ~]# ls
811.c  812.c  anaconda-ks.cfg  document  initial-setup-ks.cfg  name
[root@hac-cent-jef ~]# ls &> /dev/null
[root@hac-cent-jef ~]# lss &> /dev/null
[root@hac-cent-jef ~]# cat /dev/null
[root@hac-cent-jef ~]# 

讲完了输出,我们来研究一下输入吧~

在此之前,我们先来认识tr命令吧!


tr : 进行字符的替换


用法:

tr [optiom]… SET1 [SET2]
将SET1中的字符替换为SET2中对位的字符

注意:tr命令只是改变了文件内容输出在屏幕上的结果,而并不改变该文件的内容;

接着来说输入重定向:

  • 输入重定向 : <

与tr命令结合来举例:

(1)将文件document中的所有小写字母换成大写字母输出

[root@hac-cent-jef ~]# tr [a-z] [A-Z] < document
811.C
812.C
ANACONDA-KS.CFG
DOCUMENT
INITIAL-SETUP-KS.CFG
HELLO WORLD

(1)将文件document中的所有数字换成字母输出

[root@hac-cent-jef ~]# tr [0-9] [a-z] < document
ibb.c
ibc.c
anaconda-ks.cfg
document
initial-setup-ks.cfg
hello world

还有一个重要的知识点:

Here document <<

用法:

cat << EOF : 从键盘输入数据并以EOF为结束符
cat > FILE << EOF :将从键盘输入的数据保存到文件中,并以EOF为结束符

示例:

[root@hac-cent-jef ~]# cat << EOF
> Hello
> world
> !
> EOF
Hello
world
!

[root@hac-cent-jef ~]# cat > name << EOF
> JOHN
> LILY
> CHERRY
> JEFFREY
> EOF
[root@hac-cent-jef ~]# cat name
JOHN
LILY
CHERRY
JEFFREY

最后介绍inux中的非常重要的工具:管道

什么是管道:

连接程序,实现将一个命令的输出直接定向后一个程序输入

用法:

COMMAND1 | COMMAND2 | COMMAND3

示例1:将命令执行结果中的小写字母全部替换为大写字母

[root@hac-cent-jef ~]# cat /etc/issue
\S
Kernel \r on an \m

[root@hac-cent-jef ~]# cat /etc/issue | tr 'a-z' 'A-Z'
\S
KERNEL \R ON AN \M

示例2:只显示who命令输出结果的第一行,然后把第一行中的小写字母换成大写字母,最后删除所有输出结果中包含的所有数字

[root@hac-cent-jef ~]# who
jeffrey  pts/1        2018-08-30 23:28 (:0)
jeffrey  :0           2018-08-30 14:36 (:0)

[root@hac-cent-jef ~]# who | head -1
jeffrey  pts/1        2018-08-30 23:28 (:0)

[root@hac-cent-jef ~]# who | head -1 | tr 'a-z' 'A-Z'
JEFFREY  PTS/1        2018-08-30 23:28 (:0)

[root@hac-cent-jef ~]# who | head -1 | tr 'a-z' 'A-Z' | tr -d '0-9'
JEFFREY  PTS/        -- : (:)

此时此刻,让我们再来学习一个新的命令吧!


tee : 将输入数据流显示到屏幕上,同时保存到文件中


用法:

COMMAND | tee /PATH/TO/SOMEFILE

示例:把cat命令的结果输出到屏幕上,同时保存到文件/tmp/issue.tee中

[root@hac-cent-jef ~]# cat /etc/issue | tee /tmp/issue.tee 
\S
Kernel \r on an \m

[root@hac-cent-jef ~]# cat /tmp/issue.tee
\S
Kernel \r on an \m

我们不如来做个练习吧!

练习1:把/etc/passwd文件中的前6行的信息转换为大写字符后输出

[root@hac-cent-jef ~]# cat /etc/passwd | head -6 | tr 'a-z' 'A-Z'
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
BIN:X:1:1:BIN:/BIN:/SBIN/NOLOGIN
DAEMON:X:2:2:DAEMON:/SBIN:/SBIN/NOLOGIN
ADM:X:3:4:ADM:/VAR/ADM:/SBIN/NOLOGIN
LP:X:4:7:LP:/VAR/SPOOL/LPD:/SBIN/NOLOGIN
SYNC:X:5:0:SYNC:/SBIN:/BIN/SYNC

好啦!以上就是本此分享的所有内容了,若有错误,欢迎批评指正!

白白!

猜你喜欢

转载自blog.csdn.net/rdgfdd/article/details/82194458