Liunx学习笔记 - 07 - 01 Shell基础
1 Shell基础
Shell简介
顾名思义,shell就是壳,就跟蛋壳一样,其联通了外部环境与内部核心,所以:
- Shell是一个命令解释器,将系统指令与系统内核连接起来,并最终反映在硬件操作上;
- Shell是一个功能强大的编程语言,其属于解释性执行语言,无需编译,可直接执行;
- Shell中可直接调用Linux的命令。
Shell的分类(类似于c、c++等不同的与计算机沟通的语言)
- /bin/sh(已被/bin/bash所替代)
- /bin/bash(Linux默认的shell)
- …(其他shell)
用vi /etc/shells可以查询Linux所支持的shell,其实之前讲用户配置文件的时候,在/etc/passwd文件中最后一列就是标明用户的shell是神马shell了。
2 Shell的变量功能
2.1 变量设置=、显示echo与删除unset
用等号来设置变量,语法:变量名=变量内容。
用echo来查看变量内容,语法:echo ${变量名}或echo $变量名。
用unset来删除变量,语法:unset 变量名。
变量的设置规则
- 变量与变量内容用一个等号“=”来连接,如下:
myName=meiguanhua # 设置变量myName,其内容为字符串meiguanhua
- 等号两边不能直接跟空格,必须紧接着写(对于习惯写C++,等号两边打空格来排版整齐的程序员需要克服一下了),下面都是错误的范例:
myName =meiguanhua # 不合法,等号左边有空格
myName= meiguanhua # 不合法,等号右边有空格
myName = meiguanhua # 不合法,等号两边有空格
- 变量名称只能是英文字母、数字和下划线,但是不能以数字开头,下面就是错误范例:
6myName=meiguanhua # 不合法,以数字6开头
my_Name=meiguanhua # OK
_Name=meiguanhua # OK
- 变量内容若有空格,则需要用双引号或者单引号把变量内容包含起来,但是双引号内的特殊字符如$等,保留其原本特性,而单引号中的特殊字符则视为一般字符,不具备特殊意义。如:
myName="Mei Guanhua" # 设置myName变量,其内容为Mei Guanhua
myName='Mei Guanhua' # 同上
myEnglishName="$myName Sky" # echo $myEnglishName可见Mei Guanhua Sky
myEnglishName='$myName Sky' # echo $myEnglishName可见$myName Sky
- 可用转义符“\”(右斜杠)将特殊符号(如[Enter]、$、\、空格符、!等)变为一般字符。
- 在一串命令中,若需要其他命令提供的信息,可以使用反单引号`命令`或$(命令),反单引号为数字1左边的那个键,推荐使用$(命令)的方法,因为反单引号容易和单引号混淆,例如:
myName=$(whoami) # whoami查询当前用户是谁,那么$(whoami)即将用户名meiguanhua作为内容,=赋给变量
version=$(uname -r) # uname -r查询内核版本,变量version被赋给了内核版本,echo查看可见5.0.0-37-generic
- 若想在变量后增加内容,可用"$变量名"或${变量名}累加内容的方法来实现,如下:
myName="Mei Guanhua" # 设置myName变量为Mei Guanhua
myName="$myName"Guanqiu # 将myName变量后面添上Guanqiu,echo可见Mei GuanhuaGuanqiu
myName=${myName}Guanri # 将myName变量后面添上Guanri,echo可见Mei GuanhuaGuanqiuGuanri
PATH=${PATH}:/home/bin # 在执行文件查找路径的PATH变量下追加路径
- 若该变量需要在其它子进程执行,则需要用export来使变量成为环境变量。
myName="Mei Guanhua" # 设置变量myName
bash # 打开一个新的子进程
echo $myName # 发现子进程中并无myName变量
exit # 退出子进程
export myName # 将myName申明成环境变量(全局变量)
bash # 打开子进程
echo $myName # 发现myName变量已经可以识别了
exit # 退出子进程
- 通常大写字符为系统默认变量,自行设置的变量用小写字符表示,以便区分。
- 取消变量用unset 变量名即可,如:
unset myName # 删除变量myName
2.2 默认环境变量与变量查看命令env、set、export
用env命令可以查看当前shell环境下所有默认的环境变量及其内容,如:
- HOME=/home/meiguanhua,即用户的家目录HOME,其内容为/home/用户名。
- SHELL=/bin/bash,即当前的shell是啥。
- PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin,即执行文件的查找路径,目录和目录用冒号分隔,文件的查找是依照PATH中的目录排序进行的,所以呢,排序也很重要的,先找到哪个就执行哪个了。
- LANG=zh_CN.UTF-8,即语言系统是哪个。
用set命令可以查看所有的变量(包含环境变量和自定义变量)。这里的变量非常庞杂,其中有个PS1的定义的是命令提示符,可以用来自定义命令提示符的格式;还有个名为$的变量和名为?的变量,也蛮好玩的。
$本身也是个变量,其内容是当前Shell的线程代号,即PID(Process ID),用echo $$查看其内容,即可得到当前Shell线程的PID号,我这里显示的是2205。
?也是个变量,其内容是上个命令的回传值,如果上个命令正确执行,则回传值是0,否则是一个非零的值,不同的值代表不同的错误类型,有点类似C++的main函数return一个0哈。例如:
ll # 查看下目录和文件列表,显然可以被正确执行
...... # 命令的执行结果直接省略掉
echo $? # 查看下变量?的值,发现是0
abcdefg # 随便敲个不存在的命令,让它发错误
echo $? # 查看下变量?的值,发现是127错误
用export 变量名的方法,可以将局部变量(自定义变量)转化为全局变量(环境变量),见2.1中的例子。
2.3 变量的键盘读取、数组和声明:read、array、declare
变量除了可以用命令行设置外,还可以从键盘读取,更为灵活,且有交互性,用read命令即可。
语法:read [-pt] 变量名
选项:
-p 可以接提示符
-t 可以接等待的秒数
例:
read myName # 从键盘读取变量myName的内容
Mei Guanhua # 输入Mei Guanhua并回车
echo $myName # 查看下变量内容,显示Mei Guanhua
read -p "Please input your name: " -t 30 myName # 从键盘读取myName变量,等待30s,输出提示语句
Please input your name: MeiGuanhua # 在提示语句后面输入Mei Guanhua并回车
echo $myName # 查看下变量内容,显示Mei Guanhua
declare与typeset是一样的,用于声明变量的类型,如果declare后面不加任何参数,则会输出所有的变量名称和内容,就和用set是一样的。
语法:declare [-aixr] 变量名
选项:
-a 数组类型
-i 整数类型
-x 与export一样,环境变量
+x 取消环境变量设置
-r readonly类型,变量内容不可更改不可重设,有点像C++里面的const常变量
-p 单独列出变量的类型
例:
sum=1+2+3
echo $sum # 并不会显示6,而是显示1+2+3,因为默认的变量类型是字符型串!
declare -i sum=1+2+3 # 声明为整形变量才好使
echo $sum # 这样子才会显示6,即声明的时候把变量声明成整形才可以!
sum=$((1+2+3)) # 这样也可以
echo $sum # 会显示6
echo $((1+2+3)) # 同样显示6
注意:
- 若想对数字进行运算,则可以采用declare -i sum=1+2+3这种方式将运算表达式的结果赋给整数型变量,或者采用sum=$((1+2+3))的方式,即把运算式用两个小括号括起来,前面加美元符号,来表明取得该运算表达式的值。
- bash环境中的数值运算,仅支持整数型的,所以1/2算出来的结果是0。
declare -x sum # 将sum转变成环境变量
export | grep "sum" # export查看下并grep提取含sum的行,显示declare -ix sum="6",表明是环境变量
declare +x sum # 取消sum的环境变量
export | grep "sum" # 啥也没有了
declare -r sum # 将sum设为只读变量
sum=abcdefg # 发现无法更改,显示bash: sum: 只读变量
declare -p sum # 查看变量类型,显示declare -ir sum="6"
注意,一旦把变量设置为只读,是没法恢复的,只能注销再登陆才能复原该变量类型。
array数组类型变量的设置,直接用 变量名[index]=content 的方式即可给数组的第index个变量赋content的内容,例:
pointXYZ[1]=x # 数组pointXYZ的第1个元素为x
pointXYZ[2]=y # ...............2......y
pointXYZ[3]=z # ...............3......z
echo ${pointXYZ[1]}, ${pointXYZ[2]}, ${pointXYZ[3]} # 挨个查看数组pointXYZ的内容,显示x,y,z
x[1]=1 #
x[99]=99 # 看来这里的index只是标号而已,没必要连续给
declare -p x # 显示declare -a x=([1]="1" [99]="99"),这样也可以的,index不用连续的
2.4 变量内容的删除、替代和替换
删除与替换
变量设置方式 | 功能 |
---|---|
${变量#关键字} | 若变量从头开始的数据符合“关键字”,则将符合的最短数据删除 |
${变量##关键字} | 若变量从头开始的数据符合“关键字”,则将符合的最长数据删除 |
${变量%关键字} | 若变量从尾向前开始的数据符合“关键字”,则将符合的最短数据删除 |
${变量%%关键字} | 若变量从尾向前开始的数据符合“关键字”,则将符合的最长数据删除 |
${变量/旧字符串/新字符串} | 若变量内容符合“旧字符串”,则第一个旧字符串会被新字符串替换 |
${变量//旧字符串/新字符串} | 若变量内容符合“旧字符串”,则全部的旧字符串会被新字符串替换 |
例:
path=$PATH # 将PATH暂存成path,以防不慎整乱
echo $path # 查看下,显示如下:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
echo ${path#/*local/bin:} # 从头开始查找,将path中符合“/*local/bin:”的最短字段删除,注意*为通配符,代表0到无穷个任意字符,如此会将path中“/usr/local/sbin:/usr/local/bin:”删除,显示如下:
/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
echo ${path#/*:} # 从头开始查找,将path中符合“/*:”的最短字段删除,即只删除了第一个目录,显示如下:
/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
echo ${path##/*:} # 同上,只是这次是将最长字段删除,故只保留了最后一个目录,显示如下:
/snap/bin
echo ${path%:*bin} # 从尾向前查找,将path中符合“:*bin”的最短字段删除,即删除了最后一个目录,显示如下:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
echo ${path%%:bin} # 同上,不过这次是删除最长字段,所以只保留了第一个目录,显示如下:
/usr/local/sbin
echo ${path/sbin/SBIN} # 把path中的第一个“sbin”替换为“SBIN”,显示如下:
/usr/local/SBIN:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
echo ${path//sbin/SBIN} # 把path中的全部“sbin”替换为“SBIN”,显示如下:
/usr/local/SBIN:/usr/local/bin:/usr/SBIN:/usr/bin:/SBIN:/bin:/usr/games:/usr/local/games:/snap/bin
变量设置与替代
变量设置方式 | str没有设置(不存在) | str为空字符串 | str已设置为非空字符串 |
---|---|---|---|
var=${str-expr} | var=expr | var= | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var= | var=expr | var=expr |
var=${str:+expr} | var= | var= | var=expr |
var=${str=expr} | str=expr; var=expr | str不变; var= | str不变; var=$str |
var=${str:=expr} | str=expr; var=expr | str=expr; var=expr | str不变; var=$str |
var=${str?expr} | expr输出至stderr | var= | var=$str |
var=${str:?expr} | expr输出至stderr | expr输出至stderr | var=$str |
例1,关于减号,若旧变量str存在,就用旧变量str给新变量var赋值,不然用expr来赋值
unset str # 用unset将str变量删除,此时str变量不存在
var=${str-newvar} # 用减号“-”来判断赋值,由于str不存在,故var=newvar
echo var=“$var”, str="$str" # 显示如下
var=newvar, str=
str= # 试下str为空字符串的情况
var=${str-newvar} # 用减号“-”来判断赋值,由于str存在且为空,故var=空
echo var=“$var”, str="$str" # 显示如下
var=, str=
str=HelloWorld # 试下str存在且非空有值的情况
var=${str-newvar} # 用减号“-”来判断赋值,由于str存在且非空,故var=$str
echo var=“$var”, str="$str" # 显示如下
var=HelloWorld, str=HelloWorld
例2,关于问号?若旧变量str存在,则用旧变量str给新变量var赋值,不然就报错expr
unset str # 清空,让str变量不存在
var=${str?无此变量} # 由于str不存在,所以直接报错,如下:
bash: str: 无此变量
其实不用这些玩意儿,直接用if…then…的方法也可以,只是要多写几行代码罢了。
3 命令别名与历史命令
3.1 命令别名设置:alias,unalias
就像吃饭又叫用膳、用餐、进食一样,我们也可以给命令来设置别名,比如,如果用ls来查看的目录文件架构比较多,则一下子就到底了,那么可以用管道符“|”和more来分页查看,即经常用组合命令来做查看:
ls -l | more
每次都敲这么多感觉好烦,不如将上面的做一个别名叫“lm”的,如下:
alias lm='ls -l | more'
这样,每次只要敲lm就代表了ls -l | more的操作。如果想知道现在有哪些别名的话,直接alias回车就看到了:
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'
不难发现,系统自带的别命中,ls即把默认的ls改成了带颜色color显示,而ll则是把ls又加上了a全部,l详细信息,F(在列出的文件名称后加一符号;例如可执行档则加 “*”, 目录则加 “/”),确实提供了很大的方便。
如果想取消别名,直接用 unalias 别名 就可以了,如:
unalias lm
3.2 历史命令history
实际上,用户敲入的命令会被保存下来,且能用history命令查看。
用法 | 功能 |
---|---|
history | 列出所有历史命令(默认大概1000条,由环境变量HISTSIZE决定) |
history n | 列出最近的条历史命令 |
history -c | 清除目前shell中所有的history内容 |
history [-arw] histfiles | -a将目前新增的history命令新增写入histfiles中,若不指定histfiles,则写入默认 ~/.bash_history |
-r将histfiles的内容读到目前这个shell的history记忆中 | |
-w将目前的history记忆内容写入histfiles中 |
除了查询这些历史命令之外,还可以直接执行这些历史命令,比如:
用法 | 功能 |
---|---|
!n | 执行第n条历史命令 |
!! | 执行上一个命令 |
!command | 执行以command开头的最近一次历史命令 |
当然,也可以用上下方向键来选择最近的历史命令,然后回车执行。
相对比较简单,就不做示例了。
4 Bash操作环境:快捷键、通配符、特殊符号
bash环境下的组合按键及其功能
快捷键 | 功能 |
---|---|
Ctrl+c | 终止目前的命令,比如它卡死的时候,直接把它卡掉 |
Ctrl+d | 输入结束(EOF),例如用mail写邮件表示结束的时候 |
Ctrl+m | 就是回车 |
Ctrl+s | 暂停屏幕输出 |
Ctrl+q | 恢复屏幕输出 |
Ctrl+u | 在提示符下,将整行命令删除 |
Ctrl+z | 暂停目前命令 |
Ctrl+l | 清屏 |
通配符
符号 | 意义 |
---|---|
* | 代表0到无穷多个任意字符 |
? | 代表1个任意字符 |
[] | 代表1个在中括号中的字符,如[abcd]代表a、b、c、d中的1个字符 |
[-] | 代表在编码顺序内的所有字符,如[0-9]代表0-9之间的所有数字 |
[^] | 括号内第1个字符为 ^ 表示反向选择,如 [^abc] 代表非a、b、c三者的其它1个字符 |
例:
mkdir tmpTest; cd tmpTest; touch a a1 a2 a3 aa ab ac aaa; # 新建测试目录,进入,新建测试文件
ls # 显示所有文件,可见:a a1 a2 a3 aa aaa ab ac
ls a* # 显示a开头的任意字符长度文件,可见:a a1 a2 a3 aa aaa ab ac
ls a? # 显示a开头且共2个字符的文件,可见:a1 a2 a3 aa ab ac
ls a[a-b] # 显示:aa ab
ls a[^a-z] # 显示:a1 a2 a3
ls ??? # 显示:aaa
特殊符号
符号 | 意义 |
---|---|
# | 注释符号,用在script脚本中,其后数据均不执行 |
\ | 转义符,将“特殊字符或通配符”转化为一般字符,要想用\直接写俩\\就好了 |
| | 管道符,分隔两个管道命令的界定,前一个的输出为后一个的输入 |
; | 连续命令执行分隔符,即可以把多个命令写到一行,用分号隔开即可 |
~ | 用户的主文件夹,即/home/用户名 |
$ | 变量前导符,$变量名 将变量内容取出 |
& | 作业控制,将命令变成在背景下操作 |
! | 逻辑非 |
/ | 目录符号,路径分隔符 |
>, >> | 数据流重定向,输出导向,分别为“替换”和“累加” |
<, << | 数据流重定向,输入导向 |
‘’ | 单引号,不具有变量置换功能 |
“” | 双引号,具有变量置换功能 |
`` | 反引号,两个反引号中间为先执行的命令,也可以用$()来实现 |
() | 中间为子shell的起始与结束 |
{} | 中间为命令块的组合 |
5 数据流重定向
命令执行的正确结果(标准输出)和错误结果(标准错误输出)都会输出到屏幕上,但有时候不想让它输出到屏幕上,想让它写入到文件中,比如CFD计算出来的很多数据,想要拿出来回头慢慢分析,这就是数据流重定向,很简单,在命令执行语句后面添加上想让它的执行结果输出到哪里去的语句就可以了。
- 标准输入(stdin):代码为0,使用<或<<
- 标准输出(stdout):代码为1,使用>或>>,这里默认是stdout,所以省略了代码1
- 标准错误输出(stderr):代码为2,使用2>或2>>
- >是用覆盖的方式写入,而>>是用追加的方式写入
- 若想把正确和错误输出都写到一个文件里,用2>&1或者&>即可
例-输出重定向:
mkdir tmpTest; cd tmpTest; touch aa; # 新建测试目录,进入该目录,新建测试文件
find a* b* 1>_right 2>_error # 查找,并将标准输出写入_right,标准错误输出写入_error文件
# 屏幕上没有任何显示,但是ls可见多了两个文件_right和_error,cat查看这俩文件
cat _right # 显示aa
cat _error # 显示find: ‘b*’: 没有那个文件或目录
find a* b* &>_rightError # 将标准输出和标准错误输出写到1个文件里去
cat _rightError # 显示如下:
aa
find: ‘b*’: 没有那个文件或目录
注意:
不能用1>file 2>file的方式企图用同名文件来让正确与错误输出写入到同一文件里去,因为这样子的话,正确和错误的输出会交错凌乱地写入到一个文件里,而非把正确和错误分开写入到一个文件的前面和后面。
如果既不想在屏幕上看到输出,也不想弄个文件让它输出到里面,那么直接用>/dev/null就好了,这个相当于垃圾箱,即直接把输出扔到垃圾箱里面了。
6 命令的顺序执行与逻辑执行:;、&&、||
可以用分号“;”实现多个命令的连续执行,不论前面命令有没有正确执行,后面命令都会执行。
例:
mkdir tmpTest; cd tmpTest; touch a1 a2; # 前面展示过了,就是把多个命令写到一行
sync; sync; shutdown -h now; # 执行两次sync同步写入磁盘,然后关机
可以用“&&”和“||”来逻辑执行多个命令,前者只有在上个命令正确执行的情况下才会执行后续命令,而后者则只有在上个命令报错的情况下才会执行后续命令,即:
命令 | 意义 |
---|---|
com1; com2 | 执行完com1后执行com2 |
com1 && com2 | 执行com1,若正确执行($?等于0)则执行com2,若错误($?不等于0)则不执行com2 |
com1 || com2 | 执行com1,若错误($?不等于0)则执行com2,若正确执行($?等于0)则不执行com2 |
例:
# 看下tmpTest目录存在否,不存在的话就创建tmpTest目录
ls tmpTest || mkdir tmpTest
# 在tmpTest目录下创建testFile文件,可以用 || 联合 && 来实现
# 先ls查看有没有tmpTest目录,如果没有,就创建tmpTest目录,并在该目录下创建testFiles文件;
# 若该目录存在,则直接在该目录下面新建testFile文件。
ls tmpTest || mkdir tmpTest && touch ./tmpTest/testFile
7 管道命令(pipe)
管道符号“|”用来连接两个命令,即把前一个命令的输出作为后一个命令的输入来处理。比如有时会ll出来的目录文件非常多,一下子就到底了,看起来很不方便,想把这个用cat、more、less、head、tail、vi、vim等查看,就可以这么整:
ll /etc | more # 将ll /etc的结果(列出/etc目录下的目录文件详情)用more查看
- 管道命令仅能处理standard output(标准输出),对于standard error output(标准错误输出)则直接忽略。
- 管道命令必须要能够接收前一个命令的数据成为standard input继续处理才行,即“|”后的命令要能够处理前面命令的标准输出才行。
除了能显示标准输出,还可以对标准输出做一些特定的操作。
7.1 选取命令:cut、grep
cut是切割,用来将一段信息中的某一段切割出来,其处理的信息是以行为单位。这个cut有点像是windows当中写字板里整了个表格,然后导入到excel里去,用冒号隔开,然后一列一列的,把第n列选出来的意思。
若用分隔符隔开(如常见的冒号、分号等),来取第n个字段,则:
cut -d ‘分隔字符’ -f fields
若想取出第n1到n2个位置范围内的字符,则:
cut -c 字符范围
echo $PATH # 查看下命令查找路径PATH的内容,如下
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
echo $PATH | cut -d ':' -f 5 # 用冒号做分隔符分隔,取出第5个字段,即/sbin,显示如下
/sbin
echo $PATH | cut -d ':' -f 2,5 # 同上,只是要同时取出第2和第5字段,显示如下
/usr/local/bin:/sbin
export # 显示所有环境变量,如下:
declare -x CLUTTER_IM_MODULE="xim"
declare -x COLORTERM="truecolor"
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
……后面太长了省略掉……
export | cut -c 12- # cut选取12个字符之后的字段,也就是环境变量的名字和内容部分,显示如下:
CLUTTER_IM_MODULE="xim"
COLORTERM="truecolor"
DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
……后面太长了省略掉……
注意: cut在用空格做分隔的时候,只会识别单个空格,即如果多个空格相连的情况,它会认为它们都是分隔符,而不是一个分隔符,所以cut处理多空格相连的数据时不太灵光。
grep命令用来撷取一行数据,即若找到相匹配的项,就把该匹配项所在行给列出来。所以呢,cut实际上是选取的列,而grep实际上选取的是行。
用法:
grep [-acinv] [–color=auto] ‘查找字符串’ filename
选项:
-a 将binary文件以text文件的方式查找数据
-c 计算找到’查找字符串’的次数
-i 忽略大小写的不同,所以大小写视作相同
-n 顺便输出行号
-v 反向选择
–color=auto 将找到的关键字用颜色标识(这个默认都整成alias都是有的,设不设无所谓的)
last | grep 'mei' # 用last查询用户登录信息,并把mei这个用户提取出来,显示如下
meiguanh :0 :0 Mon Jan 6 14:10 gone - no logout
meiguanh :0 :0 Mon Jan 6 09:12 - 09:57 (00:44)
last | grep -v 'mei' # 看看除了用户mei之外,别的用户的登陆情况
history | grep -c 'll' # 看看用了多少次的ll命令,显示130次
cat /etc/passwd | grep 'mei' # 看下mei的密码配置文件
7.2 排序命令:sort、wc、uniq
sort命令常用于排序
用法:
sort [-fbMnrtuk] [file or stdin]
选项:
-f 忽略大小写,如A和a视作一样
-b 忽略最前面的空格部分
-M 以月份的名字来排序,如JAN、DEC等
-n 使用“纯数字”进行排序
-r 反向排序
-u 为uniq,相同的数据中,仅出现一行代表
-t 分隔符,默认用tab来分隔
-k 以哪个区间进行排序
例:
cat /etc/passwd | sort # 用户配置信息做个排序看看,默认是a-z排序的,如下:
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
avahi-autoipd:x:106:112:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/usr/sbin/nologin
avahi:x:116:122:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
colord:x:117:123:colord colour management daemon,,,:/var/lib/colord:/usr/sbin/nologin
……后面太长了省略掉……
cat /etc/passwd | sort -t ':' -k 3 # 用冒号分隔开,然后以第3字段来排序,即UID排序
root:x:0:0:root:/root:/bin/bash
meiguanhua:x:1000:1000:meiguanhua,,,:/home/meiguanhua:/bin/bash
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
guyuanyuan:x:1001:1001::/home/guyuanyuan:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
……后面太长了省略掉……
好奇怪,这里1000居然排到了100的前面,因为呢,它是用字符来排序的,不是用数字来排序的,想让它用数字来排序,那就要加上-n选项了
cat /etc/passwd | sort -t ':' -k 3 -n # 用冒号分隔开,然后以第3字段来数字排序,即UID排序
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
……后面太长了省略掉……
排序完成后,重复的数据只让它显示1个,就可以用uniq命令了
用法:
uniq [-ic]
选项:
-i 忽略大小写
-c 进行计数
例:
last | cut -d ' ' -f 1 | sort | uniq -c # 用户可能登陆很多次,若想看到用户和登陆次数,这样OK
1
2 meiguanh
2 reboot
1 wtmp
wc命令是用来统计信息中的多少行、多少字、多少字符
用法:
wc [-lwm]
选项:
-l 仅显示多少行
-w 仅显示多少字(英文单词)
-m 仅显示多少字符
若啥也不加,直接wc,则把多少航、多少字、多少字符全输出来
例:
last | wc # 统计last信息中有多少行、多少字、多少字符,显示6行、49单词、332字符
6 49 332
7.3 双向重定向:tee
如果既想把数据输出到文件,又想让数据输出到屏幕,那么就要用到tee命令了。
用法:
tee [-a] file
选项:
-a 表示累加的方式写入文件file中
例:
ll | tee tmpFile # 屏幕列出当前目录详情,并同时写入到tmpFile文件里,more tmpFile可见和ll结果一样内容
ll | tee tmpFile | more # 这个把输出到屏幕的信息,再拿more来看看,而不是一股脑输出来
7.4 字符转换命令:tr、col、join、paste、expand
用得不多,不做介绍了。
7.5 切割命令:split
用得不多,不做介绍了。
7.6 参数代换:xargs
用得不多,不做介绍了。
7.7 关于减号“-”的作用
用得不多,不做介绍了。