【图文教程】 Linux shell基础知识

预习内容:

8.1 shell介绍
8.2 命令历史
8.3 命令补全和别名
8.4 通配符
8.5 输入输出重定向
8.6 管道符和作业控制
8.7/8.8 shell变量
8.9 环境变量配置文件
8.10 shell特殊符号cut命令
8.11 sort_wc_uniq命令
8.12 tee_tr_split命令
8.13 shell特殊符号下

扩展:
bashrc和bash_profile的区别 http://ask.apelearn.com/question/7719
简易审计系统(必须要预习): http://www.68idc.cn/help/server/linux/2014042190951.html
关于PROMPT_COMMAND环境变量的含义 http://www.linuxnote.org/prompt_command-environment-variables.html
source exec 区别 http://alsww.blog.51cto.com/2001924/1113112
sort并未按ASCII排序 http://blog.csdn.net/zenghui08/article/details/7938975

8.1 shell介绍:

在这里插入图片描述

Shell 俗称壳(用来区别于核),是指“提供使用者使用界面”的软件(命令解析器)。shell 类似于 DOS 下的 command 和后来的 cmd.exe 。它接收用户命令,然后调用相应的应用程序。Linux 下的shell 有很多种,CentOS7 默认 shell 为 bash 。

什么是Shell:http://c.biancheng.net/view/706.html

如果想安装zsh、ksh可以使用命令搜索,然后选择合适的版本安装:

在这里插入图片描述

同时 shell 又是一种程序设计语言。作为命令语言,它交互式解释和执行用户输入的命令或者自动地解释和执行预先设定好的一连串的命令;作为程序设计语言,它定义了各种变量和参数,并提供了许多在高级语言中才具有的控制结构,包括循环和分支。在排序算法中, shell 是希尔排序的名称。

8.2 命令历史:

众所周知 CentOS 中使用键盘向上方向键可以查看历史使用过的命令,实际上这些历史命令是在用户家目录下的一个叫 /.bash_history 的文件中存放着,可以使用 cat 命令查看一下:

[root@sc ~]# ls /root/.bash_history 
/root/.bash_history
[root@sc ~]# cat !$

使用 history 命令可以查看到这个文件存放了多少条历史命令:

[root@sc ~]# history

在这里插入图片描述

这个文件最大可以存一千条历史命令,这个数量是由一个 HISTSIZE 环境变量决定的:

[root@sc ~]# echo $HISTSIZE
1000

history -c 命令可以把当前内存的历史命令清空,这条命令仅清空内存中的历史命令, .bash_history 文件立的历史命令不会被清空:

注意:只有当退出终端的时候,内存中的历史命令才会保存到.bash_history文件里。
[root@sc ~]# history -c
[root@sc ~]# history 
   15  history 
[root@sc ~]# cat .bash_history  # 查看配置文件里历史命令,不会被清空

在 /etc 目录下的 profile 文件中可以定义 HESTSIZE 环境变量:

注意:修改完后可以使用 source /etc/profile 命令让文件生效。
[root@sc ~]# vi /etc/profile
[root@sc ~]# echo $HISTSIZE 
1000
[root@sc ~]# source /etc/profile
[root@sc ~]# echo $HISTSIZE 
5000

在这里插入图片描述

如果想要记录历史命令的时候还能记录这些命令的执行时间的话,可以重新赋值一下环境变量:

具体操作如下:HISTTIMEFORMAT=“%Y/%m%d%H:%M:%S”
[root@sc ~]# HISTTIMEFORMAT=“%Y/%m%d%H:%M:%S”
[root@sc ~]# echo $HISTTIMEFORMAT
“%Y/%m%d%H:%M:%S”
[root@sc ~]# history
 	1  “2019/040116:06:37”mount /dev/vg1/lv1 /mnt/  #可以查看命令的执行时间
    2  “2019/040116:06:37”clear
    3  “2019/040116:06:37”mkfs.xfs -f /dev/vg1/lv1
    4  “2019/040116:06:37”clear
    5  “2019/040116:06:37”umount /mnt/
    6  “2019/040116:06:37”mkfs.xfs -f /dev/vg1/lv1
    7  “2019/040116:06:37”mount /dev/vg1/lv1 /mnt/
    8  “2019/040116:06:37”ls /mnt/
    9  “2019/040116:06:37”touch /mnt/233.txt
   10  “2019/040116:06:37”echo "aaaa">/mnt/233.txt

因为以上定义环境变量方式只在当前终端下有效,如果打开新的终端就不存在此环境变量了,如果想要在所有的终端都生效的话,需要把这个环境变量配置进 /etc 目录下的 profile 文件中:

[root@sc ~]# vim /etc/profile

在这里插入图片描述

修改完后,重新登录终端就可以生效了。

[root@sc ~]# source !$
source /etc/profile

想要永久保存 .bash_history 文件中的内容,只需要授予 a 权限即可:

注意:如果不是正常退出终端的话,内存中的历史命令会保存不全,或者不会被保存。
[root@sc ~]# chattr +a ~/.bash_history 
[root@sc ~]# lsattr .bash_history
-----a---------- .bash_history

!!可以执行上一条执行的命令,例如我先执行一条ls命令然后再执行!!:

[root@sc ~]# !!
lsattr .bash_history
-----a---------- .bash_history

!+ 数字可以指定运行某条命令,例如我指定运行第 10 条命令:

[root@sc ~]# !1007
echo $HISTTIMEFORMAT
“%Y/%m%d%H:%M:%S”

!+ 命令字符串的话,会倒序往上找到那个命令并执行:

[root@sc ~]# !echo
echo $HISTTIMEFORMAT
“%Y/%m%d%H:%M:%S”

8.3 命令补全和别名:

敲一下Tab键可以补全命令或者文件目录的名称,当一个命令或文件目录的名称有一个以上时,按两下Tab键可以列出这些命令的名称和文件目录的名称:

[root@sc ~]# ls
ls        lscpu     lsipc     lsmem     lspci
lsattr    lshw      lslocks   lsmod     lsscsi
lsblk     lsinitrd  lslogins  lsns      
[root@sc ~]# mk
mkdict            mkfs.ext4
mkdir             mkfs.minix
mkdumprd          mkfs.xfs
mke2fs            mkhomedir_helper
mkfifo            mkinitrd
mkfs              mklost+found
mkfs.btrfs        mknod
mkfs.cramfs       mkpasswd
mkfs.ext2         mkswap
mkfs.ext3         mktemp

CentOS7 可以自动补全命令的参数,但是默认是不支持的,需要安装一个工具,安装完这个包后,需要 reboot 操作系统后才能生效:

[root@sc ~]# yum install -y bash-completion
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
epel/x86_64/metalink         | 4.5 kB     00:00     
 * epel: mirror.premi.st
base                         | 3.6 kB     00:00     
epel                         | 4.7 kB     00:00     
extras                       | 3.4 kB     00:00     
updates                      | 3.4 kB     00:00     
(1/2): epel/x86_64/updateinfo  | 1.0 MB   00:00     
(2/2): epel/x86_64/primary_db  | 6.6 MB   00:06     
正在解决依赖关系
--> 正在检查事务
---> 软件包 bash-completion.noarch.1.2.1-6.el7 将被 安装
--> 解决依赖关系完成

依赖关系解决

====================================================
 Package          架构    版本          源     大小
====================================================
正在安装:
 bash-completion  noarch  1:2.1-6.el7   base   85 k

事务概要
====================================================
安装  1 软件包

总下载量:85 k
安装大小:259 k
Downloading packages:
bash-completion-2.1-6.el7.noar |  85 kB   00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  正在安装    : 1:bash-completion-2.1-6.el7.n   1/1 
  验证中      : 1:bash-completion-2.1-6.el7.n   1/1 

已安装:
  bash-completion.noarch 1:2.1-6.el7                

完毕!
[root@sc ~]# systemctl res
rescue        reset-failed  restart
[root@sc ~]# systemctl restart network

CentOS 重启网络服务,输入下面的命令:systemctl retart network.service 或 systemctl restart network。
CentOS 启动网络服务,输入下面的命令:systemctl start network.service 或 systemctl start network。
CentOS 停止网络服务,输入下面的命令:systemctl stop network.service 或 systemctl stop network。

当一个命令太长的时候,可以给这条命令起一个简化的别名,以方便使用,输入alias可以查看系统里的命令别名:

[root@sc ~]# alias restartnet='systemctl restart network.service' 
[root@sc ~]# restartnet 
[root@sc ~]# alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias restartnet='systemctl restart network.service'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

用户家目录下的 .bashrc 文件里只存放了最基本几个命令别名,剩下的大部分别名相关文件都在 /etc 目录下的 /profile.d/ 目录里放着:

[root@sc ~]# vi .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
~                                                                                                                                                                          
~                                                                                                                                                                          
~                                                                                                                                                                          
~        
".bashrc" 12L, 176C                                                                                                                                                  
[root@sc ~]# cd /etc/profile.d/
[root@sc profile.d]# ls
256term.csh  bash_completion.sh  colorgrep.sh  colorls.sh  lang.csh  less.csh  sh.local  vim.sh      which2.sh
256term.sh   colorgrep.csh       colorls.csh   csh.local   lang.sh   less.sh   vim.csh   which2.csh

unalias 取消自定义的别名:

[root@sc profile.d]# unalias restartnet 
[root@sc profile.d]# alias 
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

8.4 通配符:

在这里插入图片描述

* 表示通配,也就是任意字符都可以的意思,不管是文件,还是目录都可以列出来:

[root@sc ~]# ls
1.txt    3.txt  7.txt            passwd.sh
233.txt  6.txt  anaconda-ks.cfg  ys
[root@sc ~]# ls *.txt
1.txt  233.txt  3.txt  6.txt  7.txt
[root@sc ~]# ls *txt*
1.txt  233.txt  3.txt  6.txt  7.txt
[root@sc ~]# ls 1*
1.txt

? 表示任意一个字符,仅限单个字符,一个以上的字符则不包括,* 则是包括多个字符的:

[root@sc ~]# touch a.txt
[root@sc ~]# touch bb.txt
[root@sc ~]# ls ?.txt
1.txt  3.txt  5.txt  7.txt
2.txt  4.txt  6.txt  a.tx

方括号里可以指定一个范围:

[root@sc ~]# ls [0-3].txt
1.txt  2.txt  3.txt
[root@sc ~]# ls [123].txt
1.txt  2.txt  3.txt
[root@sc ~]# ls [23].txt
2.txt  3.txt
[root@sc ~]# ls [13].txt
1.txt  3.txt
[root@sc ~]# ls [0-9].txt
1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt
[root@sc ~]# ls [0-9a-z].txt
1.txt  3.txt  5.txt  7.txt
2.txt  4.txt  6.txt  a.txt
[root@sc ~]# ls [0-9A-Z].txt
1.txt  3.txt  5.txt  7.txt  B.txt
2.txt  4.txt  6.txt  A.txt

大括号里也可以指定一个范围,类似于方括号的第二种用法,只不过大括号里需要加逗号,相对于方括号看起来要直观一些:

[root@sc ~]# ls {1,2,4,7,a,B}.txt
1.txt  2.txt  4.txt  7.txt  a.txt  B.txt

8.5 输入输出重定向:

>就是把前面命令的输出的内容输入到后面这个文件中,会覆盖后面那个文件本身的内容:

[root@sc ~]# cat 1.txt
asdfsafsadfsaf
asdfsdafsadfsda
asdfdsafadsfdsa
sdadfsadfsadf
asdfdsafdsaf
[root@sc ~]# cat 1.txt >2.txt
[root@sc ~]# cat 2.txt 
asdfsafsadfsaf
asdfsdafsadfsda
asdfdsafadsfdsa
sdadfsadfsadf
asdfdsafdsaf

>>则不会覆盖后面那个文件的内容,也就是追加的意思:

[root@sc ~]# cat 1.txt >>2.txt 
[root@sc ~]# cat 2.txt 
asdfsafsadfsaf
asdfsdafsadfsda
asdfdsafadsfdsa
sdadfsadfsadf
asdfdsafdsaf
asdfsafsadfsaf
asdfsdafsadfsda
asdfdsafadsfdsa
sdadfsadfsadf
asdfdsafdsaf

2> 会把命令产生的错误信息输出到指定的文件里去,会覆盖指定的文件的内容:

[root@sc ~]# lsaaa
-bash: lsaaa: 未找到命令
[root@sc ~]# lsaaa 2>a.txt
[root@sc ~]# cat a.txt
-bash: lsaaa: 未找到命令

2>> 则不会覆盖指定的文件的内容,也就是追加的意思:

[root@sc ~]# lsaaa 2>>a.txt
[root@sc ~]# cat a.txt 
-bash: lsaaa: 未找到命令
-bash: lsaaa: 未找到命令

&> 是结合了>+2>,也就是错误信息和正确信息都会输出到指定内容,并且会覆盖指定文件本身的内容:

[root@sc ~]# ls [12].txt aaa.txt &>a.txt
[root@sc ~]# cat a.txt 
ls: 无法访问aaa.txt: 没有那个文件或目录
1.txt
2.txt

&>> 就能追加内容:

[root@sc ~]# ls [12].txt aaa.txt &>>a.txt
[root@sc ~]# cat a.txt 
ls: 无法访问aaa.txt: 没有那个文件或目录
1.txt
2.txt
ls: 无法访问aaa.txt: 没有那个文件或目录
1.txt
2.txt

还有以下这种用法:

[root@sc ~]# ls [12].txt aaa.txt >1.txt 2>a.txt
[root@sc ~]# cat 1.txt
1.txt
2.txt
[root@sc ~]# cat a.txt
ls: 无法访问aaa.txt: 没有那个文件或目录

< 输入重定向,可以把右边文件的内容输入到左边的命令里面去,使用 < 输入重定向时左边必须是命令,如果是文件的话是不行的:

[root@sc ~]# wc -l <1.txt 
2
[root@sc ~]# 2.txt <1.txt 
-bash: 2.txt: 未找到命令

8.6 管道符和作业控制:

在这里插入图片描述

管道符:

管道符可以把一个文件的输出内容,传递给后面的命令:

所以管道符简单的说就是把前面的命令执行结果交给后面的命令执行。
[root@sc ~]# cat 1.txt |wc -l
2

作业控制:

Ctrl+z 可以临时停止当前的命令:

这时vim的命令就被丢到后台了
[root@sc ~]# vim 1.txt 

[1]+  已停止               vim 1.txt

现在如果想要继续 vim 命令,就需要使用 fg 命令:

[root@sc ~]# fg
vim 1.txt

1.txt
2.txt
~                                                
~                                                
~                                                
                                       
                               1,1          全部

Ctrl+z 可以停止多个命令,jobs 可以查看当前暂停的命令:

[root@sc ~]# vim 1.txt

[1]+  已停止               vim 1.txt
[root@sc ~]# vim aa.txt 

[2]+  已停止               vim aa.txt
[root@sc ~]# jobs
[1]-  已停止               vim 1.txt
[2]+  已停止               vim aa.txt

fg 命令加 id 号可以继续指定的命令:

[root@sc ~]# fg 1
vim 1.txt
[root@sc ~]# fg 2
vim aa.txt
[root@sc ~]# 

bg 命令可以将暂停的命令转到后台去运行,如果需要关闭输入 fg 放到前端来,然后ctrl+c关闭:

在这里插入图片描述

在命令的末尾加&符号可以将一条命令丢到后台去执行,命令在后台运行完之后会显示完成:

[root@sc ~]# sleep 100 &
[1] 7677
[root@sc ~]# jobs
[1]+  运行中               sleep 100 &

8.7/8.8 shell变量:

我们知道 PATH 是系统内置变量,还有 HOME、PWD、LOGNAME 等变量,这些变量是在系统里的配置文件规定的,env 命令可以获取到系统变量,系统的变量一般都是大写的,变量的值则可以是字符串或数字:

[root@sc ~]# env
XDG_SESSION_ID=2
HOSTNAME=sc
SELINUX_ROLE_REQUESTED=
TERM=xterm
SHELL=/bin/bash
HISTSIZE=5000
SSH_CLIENT=192.168.94.1 49575 22
SELINUX_USE_CURRENT_RANGE=
SSH_TTY=/dev/pts/0
USER=root
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
LANG=zh_CN.UTF-8
SELINUX_LEVEL_REQUESTED=
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root
LOGNAME=root
SSH_CONNECTION=192.168.94.1 49575 192.168.94.128 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
_=/usr/bin/env

set 命令也可以查看变量,不过不仅仅查看系统的变量,还能查看用户自定义的变量,在 CentOS6 之前这个命令只会显示系统变量和自定义变量,在 CentOS7 则多了很多 shell 脚本相关的东西:

[root@sc ~]# set

用户自定义变量,自定义的变量也可以在 set 里体现出来:

在这里插入图片描述在这里插入图片描述

写 shell 脚本的时候经常要使用变量,变量的命名规则:变量可以以字母、下划线开头,但是不能以数字开头:

[root@sc ~]# a1=2
[root@sc ~]# echo $a1
2
[root@sc ~]# a_1=3
[root@sc ~]# echo $a_1
3
[root@sc ~]# _a1=4
[root@sc ~]# echo $_a1
4
[root@sc ~]# 1aa=2
-bash: 1aa=2: 未找到命令
[root@sc ~]# 2aa=3
-bash: 2aa=3: 未找到命令

变量值有特殊符号时需要用单引号括起来:

[root@sc ~]# a=a b c
-bash: b: 未找到命令
[root@sc ~]# a='a b c'
[root@sc ~]# echo $a
a b c
[root@sc ~]# a="a$bc"  # 加双引号转义不了
[root@sc ~]# echo $a
a
[root@sc ~]# a='a$bc'
[root@sc ~]# echo $a
a$bc

变量的叠加:

[root@sc ~]# a=1
[root@sc ~]# b=2
[root@sc ~]# echo $a$b
12
[root@sc ~]# a='a$bc'
[root@sc ~]# b=2
[root@sc ~]# echo $a$b
a$bc2
[root@sc ~]# c="a$b"c
[root@sc ~]# echo $c
a2c
[root@sc ~]# c='a$b'c
[root@sc ~]# echo $c
a$bc
[root@sc ~]# c='a$bc'
[root@sc ~]# echo $c
a$bc
[root@sc ~]# c=a"$b"c
[root@sc ~]# echo $c
a2c

echo $SSH_TTY 命令可以查看当前在哪个终端下:

[root@sc ~]# w
 10:51:43 up  1:06,  3 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     tty1                      09:45    1:05m  0.06s  0.06s -bash
root     pts/0    192.168.94.1     09:46    7.00s  0.15s  0.02s w
root     pts/1    192.168.94.1     10:49    2:39   0.03s  0.03s -bash
[root@sc ~]# echo $SSH_TTY
/dev/pts/0

在窗口 1 自创建环境变量,在窗口 2 是不会显示的:在这里插入图片描述在这里插入图片描述

bash 命令可打开子 shell,相当于打开了一个终端:

[root@sc ~]# bash
[root@sc ~]# pstree
systemd─┬─NetworkManager─┬─dhclient
        │                └─2*[{NetworkManager}]
        ├─VGAuthService
        ├─auditd───{auditd}
        ├─chronyd
        ├─crond
        ├─dbus-daemon───{dbus-daemon}
        ├─firewalld───{firewalld}
        ├─login───bash
        ├─lvmetad
        ├─master─┬─pickup
        │        └─qmgr
        ├─polkitd───6*[{polkitd}]
        ├─rsyslogd───2*[{rsyslogd}]
        ├─sshd─┬─3*[sshd───bash]
        │      └─sshd───bash───bash───pstree
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        ├─tuned───4*[{tuned}]
        └─vmtoolsd───{vmtoolsd}
[root@sc ~]# exit
exit
[root@sc ~]# pstree
systemd─┬─NetworkManager─┬─dhclient
        │                └─2*[{NetworkManager}]
        ├─VGAuthService
        ├─auditd───{auditd}
        ├─chronyd
        ├─crond
        ├─dbus-daemon───{dbus-daemon}
        ├─firewalld───{firewalld}
        ├─login───bash
        ├─lvmetad
        ├─master─┬─pickup
        │        └─qmgr
        ├─polkitd───6*[{polkitd}]
        ├─rsyslogd───2*[{rsyslogd}]
        ├─sshd─┬─3*[sshd───bash]
        │      └─sshd───bash───pstree
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        ├─tuned───4*[{tuned}]
        └─vmtoolsd───{vmtoolsd}
[root@sc ~]# echo $aming
[root@sc ~]# linux

全局变量:

在当前终端自定义的变量在子 shell 里是查看不到的,因为这种定义的变量不是全局变量,是本地变量,如果要定义全局变量需要使用 export 命令:

[root@sc ~]# aming=linux
[root@sc ~]# echo $aming
linux
[root@sc ~]# clear
[root@sc ~]# export aming=linux
[root@sc ~]# echo $aming
linux
[root@sc ~]# bash
[root@sc ~]# echo $aming
linux
[root@sc ~]# pstree
systemd─┬─NetworkManager─┬─dhclient
        │                └─2*[{NetworkManager}]
        ├─VGAuthService
        ├─auditd───{auditd}
        ├─chronyd
        ├─crond
        ├─dbus-daemon───{dbus-daemon}
        ├─firewalld───{firewalld}
        ├─login───bash
        ├─lvmetad
        ├─master─┬─pickup
        │        └─qmgr
        ├─polkitd───6*[{polkitd}]
        ├─rsyslogd───2*[{rsyslogd}]
        ├─sshd─┬─2*[sshd───bash]
        │      └─sshd───bash───bash───bash───pst+
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        ├─tuned───4*[{tuned}]
        └─vmtoolsd───{vmtoolsd}

export 定义的全局变量是向下的,也就是说如果在子 shell 里定义的全局变量在这个子 shell 的父 shell 上是查看不到的:

[root@sc ~]# export b=123
[root@sc ~]# echo $b
123
[root@sc ~]# exit
exit
[root@sc ~]# echo $b

取消变量:

unset命令后面跟变量的名称,就可以取消掉这个变量的值:

[root@sc ~]# echo $aming
linux
[root@sc ~]# unset aming
[root@sc ~]# echo $aming

8.9 环境变量配置文件:

在这里插入图片描述

环境变量的配置文件有两大类,一是系统层次维度的配置文件在 etc 目录下,二是用户层次维度的配置文件在用户的家目录下。

profile 文件是用户登录的时候会加载到,bashrc 文件是在用户、系统执行一些 shell 脚本的时候会加载到,系统层次的 profile 和 bashrc 文件一般情况下不要去动,如果要修改的话就修改用户层次的 .bashrc_profile 和 .bashrc 文件。

.bashrc_profile 文件加载的时候会调用 .bashrc 文件, .bashrc 文件又会去调用 /etc 目录下的 bashrc 文件。

[root@sc ~]# vim .bash_profile 

在这里插入图片描述

[root@sc ~]# vim .bashrc 

在这里插入图片描述

.bashrc_loguot 文件用来定义用户退出时的需要做的一些操作,如果你想让用户退出时删除历史命令,可以把删除历史命令的命令写在 .bashrc_loguot 文件里。

PS1 变量是在 /etc 目录下的 bashrc 文件里面定义的:

[root@sc ~]# vim /etc/bashrc

在这里插入图片描述

PS1 变量就是用来配置这个字符串显示的内容的:

[root@sc ~]# cd /etc/sysconfig/network-scripts/
[root@sc network-scripts]# echo $PS1
[\u@\h \W]\$  # u=用户,h=主机名,W=目录名

例如我把大写的 W 改成小写的 w ,这样的就会显示绝对路径:

[root@sc network-scripts]# PS1='[\u@\h \w]\$'
[root@sc ~]#cd 123
[root@sc ~/123]#cd /tmp/
[root@sc /tmp]#
[root@sc /tmp]#PS1='<\u@\h \w> \$'
<root@sc /tmp> #
变颜色:PS1=’[\033[01;32m]\u@\h[\033[00m]:[\033[01;36m]\w[\033[00m]$’

在这里插入图片描述

PS2 是用在另外一种环境的,例如 mysql 的命令行:

root@sc:/tmp#echo $PS2
>
root@sc:/tmp#for i in `seq 1 100` 
> do
> echo $i
> done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
root@sc:/tmp#for i in `seq 1 100` ; do echo $i; done
root@sc:/tmp#PS2="#"
root@sc:/tmp#echo $PS2
#
root@sc:/tmp#for i in `seq 1 10`
#do
#echo $i
#done
1
2
3
4
5
6
7
8
9
10

8.10 shell特殊符号cut命令:

在这里插入图片描述

1. * 任意个任意字符通配符:

root@sc:~#ls *.txt
1.txt    3.txt  6.txt   a.txt   B.txt
233.txt  4.txt  7.txt   A.txt
2.txt    5.txt  aa.txt  bb.txt

2. ? 任意一个字符:

root@sc:~#ls ?.txt
1.txt  3.txt  5.txt  7.txt  A.txt
2.txt  4.txt  6.txt  a.txt  B.txt

3. # 注释字符:一条命令前面加注释字符的话,命令就不会执:

root@sc:~# #ls a.txt 
root@sc:~#
root@sc:~##ls a.txt #adfkdsakfjdsalfjd
root@sc:~#

4. \ 脱义字符,有些字符是命令,所以需要脱义符来让这个字符变成普通字符,而非命令字符:

root@sc:~#a=1
root@sc:~#b=2
root@sc:~#c=$a$b
root@sc:~#echo $c
12
root@sc:~#c='$a$b'
root@sc:~#c=\$a\$b
root@sc:~#echo $c
$a$b

5. | 管道符,把前面命令的输出结果交给后面的命令执行:

root@sc:~#cat /etc/passwd |wc -l
27

在这里插入图片描述

cut 命令可以分割字符串,可以指定某个字符进行分割,例如我要分割passwd 文件里的字符串,并以冒号为分割符,然后指定查看第一段字符串

在这里插入图片描述在这里插入图片描述

8.11 sort_wc_uniq命令:

sort命令可以对字符串或数字排序,排序的方法是安照ASCII码排序的,例如我排序passwd文件的内容:在这里插入图片描述

root@sc:~#head /etc/passwd >> 1.txt
root@sc:~#vim 1.txt 
root@sc:~#sort 1.txt 
<
>
]
{
1.txt
222111
222222aaaaa
223333
22aaa
2.txt
4888888888adsfdsaf
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
halt:x:7:0:halt:/sbin:/sbin/halt
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
*sdjfasdfjl
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
sync:x:5:0:sync:/sbin:/bin/sync
加 -n 选项会照数字去排序,这时相对于数字来说字母和特殊符号相当于是零:
root@sc:~#sort -n 1.txt 
<
>
]
{
adm:x:3:4:adm:/var/adm:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
halt:x:7:0:halt:/sbin:/sbin/halt
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
root:x:0:0:root:/root:/bin/bash
*sdjfasdfjl
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
sync:x:5:0:sync:/sbin:/bin/sync
1.txt
2.txt
22aaa
222111
222222aaaaa
223333
4888888888adsfdsaf
-r 则是倒序排序:
root@sc:~#sort -r 1.txt 
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
*sdjfasdfjl
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
halt:x:7:0:halt:/sbin:/sbin/halt
daemon:x:2:2:daemon:/sbin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
4888888888adsfdsaf
2.txt
22aaa
223333
222222aaaaa
222111
1.txt
{
]
>
<

wc -l 命令是统计行数的:

root@sc:~#wc -l 1.txt 
22 1.txt
加 -m 选项则是统计字符数,包括换行符:
root@sc:~#wc -m 1.txt 
468 1.txt
root@sc:~#vim 2.txt 
root@sc:~#cat 2.txt  # 往2.txt里写了6个字符
abc
123
root@sc:~#wc -m 2.txt  # 但是显示是8个字符
8 2.txt
root@sc:~#cat -A 2.txt  # 原来是有换行符存在,换行符是隐藏状态
abc$
123$
加 - w 选项是安照单词统计,这个单词是以逗号或者空格分开的一个个词:
root@sc:~#wc -w 2.txt  # 123是一个词,abc是一个词,一共两个词
2 2.txt
root@sc:~#vim 2.txt 
root@sc:~#wc -w 2.txt 
3 2.txt
root@sc:~#cat 2.txt 
abc
123 111.222  # 111,222也是一个词  

uniq 命令是去掉重复的字符,需要排序再去重:

root@sc:~#uniq 2.txt 
abc
123 111.222
123
abc
1
2
root@sc:~#cat 2.txt 
abc
123 111.222
123
abc
1
1
2
root@sc:~#sort 2.txt 
1
1
123
123 111.222
2
abc
abc
root@sc:~#sort 2.txt |uniq
1
123
123 111.222
2
abc
uniq 命令是去掉重复的字符,-c 是统计行数,配合 sort 命令使用:
root@sc:~#sort 2.txt |uniq -c
      2 1
      1 123
      1 123 111.222
      1 2
      2 abc

8.12 tee_tr_split命令:

tee 命令和输出重定向有点像,它们的区别是 tee 是可以看到输出重定向的结果, > 则不能看到:

[root@sc ~]# sort 2.txt |uniq -c >a.txt
[root@sc ~]# cat a.txt 
      2 1
      1 123
      1 123 111.222
      1 2
      2 abc
[root@sc ~]# sort 2.txt |uniq -c |tee a.txt
      2 1
      1 123
      1 123 111.222
      1 2
      2 abc
[root@sc ~]# cat a.txt
      2 1
      1 123
      1 123 111.222
      1 2
      2 abc
清空 a.txt 内容的命令:
[root@sc ~]# >a.txt
[root@sc ~]# cat a.txt 
[root@sc ~]# 
tee -a 追加重定向:
[root@sc ~]# sort 2.txt |uniq -c |tee -a a.txt
      2 1
      1 123
      1 123 111.222
      1 2
      2 abc
[root@sc ~]# cat a.txt 
      2 1
      1 123
      1 123 111.222
      1 2
      2 abc
      2 1
      1 123
      1 123 111.222
      1 2
      2 abc

tr 命令是用来替换字符的,针对字符来操作的:

在这里插入图片描述split 切割命令,可以用来切割文件,因为有些文件太大了,不方便查看,所以需要使用 split 来切割成多个文件来方便查看,split 可以针对大小切割也可以针对行数切割:

[root@sc ~]# find /etc/ -type f -name "*conf" -exec cat {} >>a.txt \;
[root@sc ~]# du -sh a.txt
448K	a.txt
[root@sc ~]# ls
123      4.txt   anaconda-ks.cfg  passwd.sh
1.txt    5.txt   a.txt            test
233.txt  6.txt   A.txt            ys
2.txt    7.txt   bb.txt
3.txt    aa.txt  B.txt
[root@sc ~]# mv a.txt test/
[root@sc ~]# cd test/
[root@sc test]# ls
a.txt

在这里插入图片描述

删除x*的文件:
[root@sc test]# rm -fr *
[root@sc test]# ls
[root@sc test]# 
指定分割的文件大小:
[root@sc test]# split -b 100k a.txt
[root@sc test]# ls
a.txt  xaa  xab  xac
指定分割的文件前缀名:
[root@sc test]# split -b 100k a.txt abc
[root@sc test]# ls
abcaa  abcab  abcac  a.txt  xaa  xab  xac
[root@sc test]# split -b 100k a.txt abc.
[root@sc test]# ls
abcaa  abc.aa  abcab  abc.ab  abcac  abc.ac  a.txt  xaa  xab  xac
指定分割的文件的行数:
[root@sc test]# split -l 1000 a.txt
[root@sc test]# ls -l
总用量 856
-rw-r--r--. 1 root root 102400 4月   3 12:40 abcaa
-rw-r--r--. 1 root root 102400 4月   3 12:42 abc.aa
-rw-r--r--. 1 root root 102400 4月   3 12:40 abcab
-rw-r--r--. 1 root root 102400 4月   3 12:42 abc.ab
-rw-r--r--. 1 root root   9252 4月   3 12:40 abcac
-rw-r--r--. 1 root root   9252 4月   3 12:42 abc.ac
-rw-r--r--. 1 root root 214052 4月   3 12:35 a.txt
-rw-r--r--. 1 root root  33754 4月   3 12:44 xaa
-rw-r--r--. 1 root root  46342 4月   3 12:44 xab
-rw-r--r--. 1 root root  44785 4月   3 12:44 xac
-rw-r--r--. 1 root root  43775 4月   3 12:44 xad
-rw-r--r--. 1 root root  33687 4月   3 12:44 xae
-rw-r--r--. 1 root root  11709 4月   3 12:44 xaf
[root@sc test]# wc -l *
  2499 abcaa
  2499 abc.aa
  2567 abcab
  2567 abc.ab
   284 abcac
   284 abc.ac
  5350 a.txt
  1000 xaa
  1000 xab
  1000 xac
  1000 xad
  1000 xae
   350 xaf
 21400 总用量

8.13 shell特殊符号下:

在这里插入图片描述

想要把多条命令写在一行里,就需要使用分号分割:

[root@sc ~]# ls 1.txt ; wc -l 2.txt
1.txt
7 2.txt

|| 是或者的意思,写在两条命令中间的话只要左边的命令执行成功,那么右边的命令就不会执行。如果左边的命令执行失败,那么右边的命令就会执行:

[root@sc ~]# ls 1a.txt || wc -l 2.txt 
ls: 无法访问1a.txt: 没有那个文件或目录
7 2.txt
[root@sc ~]# ls 1.txt || wc -l 2.txt 
1.txt

&& 是并且的意思,只有左边的命令执行成功的时候,右边才会执行,只要左边的命令没有执行成功,那么右边的命令一定不会被执行:

[root@sc ~]# ls 1a.txt && wc -l 2.txt 
ls: 无法访问1a.txt: 没有那个文件或目录
[root@sc ~]# ls 1.txt && wc -l 2.txt 
1.txt
7 2.txt

猜你喜欢

转载自blog.csdn.net/weixin_44816331/article/details/88941961