tonglin0325的个人主页

Linux学习笔记——Shell部分

1.shell命令#

shell是连接linux内核和linux命令的模块

  命令名称  /bin/sh  /bin/csh  /bin/ksh

  chsh -s  输入新的shell,即修改shell

可以使用env命令查看当前的环境变量,可以查看当前使用的是什么shell命令

1
2
env | grep SHELL
SHELL=/bin/zsh

2.使用vi编辑器#

键盘输入 功能
i 进入插入模式
esc 进入命令模式
w 将目前文件内容加以保存
q 退出,如果文件有修改会出现错误信息
q! 强制离开vi,并且不保存文件
wq 将修改过的内容保存,并离开vi
set nu 给文件中每一行添加行号
set nonu 取消行号
输入数字 直接输入数字再按esc,可将光标移至该行行首
/字符串 从头查找特定字符串
?字符串 从尾查找特定字符串

3.管道命令:pipe |#

1.把一个命令的输出作为另一个命令的输入

1
2
ls -al /etc | less

4.选取命令:cut和grep#

cut命令可以将一段消息的某段切出来。

-d接分隔符,-f是取出第几段的意思,-c是以字符串为单位取出固定的字符串范围

1
2
3
ls -F | grep '/' -v | cut -d'.' -f 1  #在取出不是文件夹的文件后,通过分隔符‘.’来分割,取出不包括文件后缀的文件名
ls -F | grep '/' -v | cut -c 1-  #取出第一个字符(包括第一个)之后范围的字符,也可以指定范围1-5

  

grep命令分析一行消息,如果其中有所需要的信息,就将该行取出。

1
2
3
4
5
ls -F | grep '/'  #取出文件夹的名字
ls -F | grep '/' -v  #反向,取出不是文件夹的文件
ls -l | grep ^d #只显示文件夹
ls -l | grep ^- #只显示文件

  

fgrep命令用于匹配文件内容

1
2
3
4
5
6
7
8
fgrep 'test' ./xxx.py
is_contain=`fgrep 'test' ./xxx.py`
if [ ! $is_contain ]; then
echo "IS NULL"
else
echo "NOT NULL"
fi

  

5.排序命令:sort、wc和uniq#

(a.txt保存的是ls -al的输出)

 使用sort命令进行排序

-f:表示忽略大小写

-b:忽略最前面的空格

-M:表示以月份的名字来排序,JAN、DEC等

-n:使用“纯数字”进行排序,10在9之后,而不会在1之后(默认是以文字类型来排序)

1
2
cat 下载/a.txt | sort -t' ' -k 6 -n

-r:表示反向排序

-u:表示uniq,相同的数据中,仅出现一行表示,(如果用第k栏来排序,第k栏相同的只出现一个)

-t:是分隔符,-k:是按某个字段来进行排序

1
2
cat 下载/a.txt | sort -t' ' -k 6    #-t表示分割,-k表示用第k栏来排序

 

 使用uniq命令来将重读的数据仅显示一次

1
2
cat 下载/a.txt | cut -d' ' -f 1,2 | sort -t' ' -k 2 -n | uniq  #取出权限和文件数,然后按文件数排序,再去重

 

 使用wc命令来统计文件的字数、行数、字符数

-l:仅显示多少行,-w:仅显示多少字(英文单词),-m:多少字符

1
2
cat 下载/a.txt | wc  #分别显示“行数、字数、字符数”

 去掉第一行的“总用量”,再统计行数

1
2
3
4
5
common@common-Aspire-4750:~$ cat 下载/a.txt | grep -v '总用量' | wc -l
81
common@common-Aspire-4750:~$ cat 下载/a.txt | wc -l
82

 

6.双向重导向:tee#

  同时将数据流分送到文件和屏幕

1
2
cat 下载/a.txt | sort | tee 下载/a.txt  #把txt的内容排序后,双向重导向,不能使用>来把一个文件的内容修改后,再重导向回本身,该操作会清空这个文件

 

7.字符转换命令:tr、col、join、paste、expand#

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

-d:删除一段消息中的文字,-s:替换重复的字符

1
2
cat a.txt | sed 's/[ ][ ]*/ /g'    #先把文件中连续的空格变成一个空格,方便使用字段来进行切分或者排序

1
2
cat a.txt | awk '{$1=$1;print}'  #去掉连续空格的其他方法

1
2
cat a.txt | tr -s ' '        #去掉连续空格的其他方法

 

1
2
cat 下载/a.txt | tr '[a-z]' '[A-Z]'    #把输出的所有小写字母替换成大写字母

1
2
cat 下载/a.txt | tr -d ' '    #删除所有的空格

 

col可以用来将【tab】按键替换成为空格键,在cat -A中,【tab】会以^I来表示,【换行符】会以^M

1
2
cat regTrees.py | col -x | cat -A    #将tab键转换成对等的空格键

 

join可以用来处理两个文件之间的数据

-t:join默认以空格符号分割数据,并且比较“第一个字段”的数据,如果两个文件相同,则将两个数据联成一行,且第一个字段放在第一个。

-i:忽略大小写的差异

-1:表示第一个文件要用哪个字段来分析

-2:表示第二个文件要用哪个字段来分析

比如第一个文件a.txt是

1
2
3
1 2 3
4 5 6

第二个文件b.txt是 

1
2
3
1 4 5
4 7 8

 

1
2
3
4
common@common-Aspire-4750:~/下载$ join -t ' ' -1 1 a.txt -2 1 b.txt
1 2 3 4 5
4 5 6 7 8

 

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

-d:后面可以接分隔符,默认以[tab]来分割

-:如果file部分写成-,表示来自标准输入的数据

1
2
3
4
common@common-Aspire-4750:~/下载$ paste a.txt b.txt
1 2 3 1 4 5
4 5 6 4 7 8

1
2
3
common@common-Aspire-4750:~/下载$ cat a.txt | paste a.txt b.txt - | head -n 3    #把要显示的文件和后面的输出贴在一起,且只取出前三行
1 2 3&nbsp;&nbsp; &nbsp;1 4 5&nbsp;&nbsp; &nbsp;1 2 3<br />4 5 6&nbsp;&nbsp; &nbsp;4 7 8&nbsp;&nbsp; &nbsp;4 5 6

 

expand将【tab】按键转换成空格键

-t:后面可以接数字,一般一个tab键可以用8个空格键来替换

unexpand将空格键转换成【tab】

1
2
expand -1 treeExplore.py    #-t表示一个[tab]按键表示多少个字符

 

8.拆分命令:split#

split命令可以用来拆分文件

-b:后接要拆分的文件大小,可加单位,例如b,k,m等

1
2
3
split -b 1k a_copy.txt a_split    #拆分之后在前缀后面加上aa、ab、ac
cat a_split* >> a_back.txt #把拆分后的文件合并

-l:按行数进行拆分

1
2
ls -al | split -l 10 - lsxiazai    #输出的信息,每10行记录成一个文件,必须要&ldquo;-&rdquo;符号

  

9.参数代换:xargs#

xargs命令可以读入stdin的数据,并且以空格符或换行符作为标示,将stdin的数据分隔成为参数,作为某个命令的参数

-0:如果输入的stdin含有特殊字符,例如`,\,空格键等字符,这个-0可以还原成一般字符。这个参数可以用于特殊状态

-e:这时EOF的意思。后面可以接一个字符串,当xargs分析到这个字符串的时候,就会停止继续工作

-p:在执行每个命令的参数的时候,都会询问用户是否执行,输入y或者n

-n:后面接次数

1
2
3
common@common-Aspire-4750:~$ cut -d':' -f 1 < /etc/passwd | xargs
root daemon bin sys ... common

1
2
cut -d':' -f 1 < /etc/passwd | xargs finger    #将输入的参数作为finger命令的输出,finger命令用于查找并显示用户信息

1
2
cut -d':' -f 1 < /etc/passwd | xargs -p -n 5 finger    #每次仅查看5个账号,且询问用户

1
2
cut -d':' -f 1 < /etc/passwd | xargs -p -e'games' finger    #当参数遇到games的时候,就包括后面的舍弃掉

 

10.减号(-)的用途#

当用到一个命令的stdout作为这次的stdin的时候,stdin和stdout可以利用“-”来替代

1
2
tar -cvf - /home | tar -xvf -    #后面的-取用前一个命令的stdout

 

11.通配符与特殊符号#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
*    #代表多个字母或者数字
? #代表一个字母或者数字
# #注释
\ #转义符号
| #分隔两个管道命令
; #连续命令的分隔
~ #用户的home目录
$ #将命令变成后台工作
! #逻辑&ldquo;非&rdquo;
/ #路径分隔符号
>、>> #输出导向
&lsquo; #单引号,不具有变量置换的功能
&ldquo; #具有变量置换的功能
&rsquo; &lsquo; #两个&lsquo;中间为可以先执行的命令
() #中间为子shell的起始与结束
[] #中间为字符的组合
{} #中间为命令区块的组合

 

1
2
3
4
5
6
7
8
ctrl+C    #终止当前面命令
ctrl+D #输入结束(EOF),例如邮件结束的时候
ctrl+M #就是Enter键
ctrl+S #暂停屏幕的输出
ctrl+Q #恢复屏幕的输出
ctrl+U #在提示符下,删除整行命令
ctrl+Z #&rdquo;暂停&ldquo;当前的命令

 

12.基础正则表达式#

grep命令

-a:在二进制文件中,以文本文件的方式搜索数据

-c:计算找到”搜索字符串“的次数

-i:忽略大小写

-n:输出行号

-v:反向选择

搜索特定字符和利用[]来搜索集合字符

1
2
3
4
5
grep -n 'the' regular-express.txt    #搜索特定字符串,输出行号
grep -n -i 'the' regular-express.txt #忽略大小写
grep -n 't[ae]st' regular-express.txt #利用[]来搜索集合字符
grep -n '[^g]oo' regular-express.txt #使用反向选择^来选择不是goo的oo单词

 行首字符^与行尾字符$

1
2
3
4
grep -n '^[A-Z]' regular-express.txt    #行首字符^,选择行首是[A-Z]的行
grep -n '\.$' regular-express.txt #行尾字符$,选择行尾是.的行
grep -n '^[^a-zA-Z]' regular-express.txt #选取行首不是英文字符的行

 

1
2
grep -n '\.$' a.txt    #把以.结尾的行输出,注意window的换行是^M$,Linux的换行是$

 任意一个字符(.)与重复字符(*)

1
2
3
4
5
6
grep -n 'g..d' regular-express.txt    #找到有g??d字符的行
grep -n 'o*' regular-express.txt #拥有空字符或者一个o以上的字符的行
grep -n 'oo*' regular-express.txt #拥有一个o的字符的行
grep -n 'ooo*' regular-express.txt #拥有两个o的字符的行
grep -n '[0-9][0-9]*' regular-express.txt #找到有任意数字的行

 限定连续重复字符范围{},使用的时候需要使用转义字符{}

1
2
3
grep -n 'o\{2\}' regular-express.txt    #找到两个o的字符串的行
grep -n 'go\{2,5\}g' regular-express.txt #找到g后面接2~5个o,然后再接一个g的字符串的行

 

13.格式化显示:printf#

\n  输出新的一行

\t  水平的tab按键

\v  垂直的tab按键

\xNN  NN为两位数的数字,可以转换数字为字符

1
2
3
printf '%s\t %s\t %s\t \n' `cat a.txt`    #``中的命令先执行,然后按格式输出,用tab分割
printf '\x45\n' #输出E

 

14.变量#

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
echo $HOME    #输出环境变量
common@common-Aspire-4750:~$ myname=123 #定义变量并输出
common@common-Aspire-4750:~$ echo $myname
123

unset myname #取消变量

name=my\ name #空格等特殊字符用\或者&ldquo; &rdquo;
name="my name"

common@common-Aspire-4750:~$ echo $name
my name
common@common-Aspire-4750:~$ name=$name\ 123 #累加变量
common@common-Aspire-4750:~$ echo $name
my name 123

common@common-Aspire-4750:~$ name=my\ name #通过export让子程序可以使用父程序的变量
common@common-Aspire-4750:~$ echo $name
my name
common@common-Aspire-4750:~$ bash
common@common-Aspire-4750:~$ echo $name

common@common-Aspire-4750:~$ exit
exit
common@common-Aspire-4750:~$ export name
common@common-Aspire-4750:~$ bash
common@common-Aspire-4750:~$ echo $name
my name&nbsp;

参考

1
2
https://www.huweihuang.com/linux-notes/shell/shell-var.html

 

15.如何判断一个变量为空#

参考:在shell中如何判断一个变量是否为空

 

16.变量的有效范围#

变量能否被引用是与export有关的,被export后的变量,可以称之为“环境变量”,环境变量可以被子程序所引用,但是其他的自定义变量就不会存在于子程序中。

在scripts2.sh会去引用scripts1.sh中的变量,那么scripts1.sh就应该设置export

 

17.变量键盘读取、数组与申明:read、array、declare#

1、read,用来读取来自键盘输入的变量

-p:后面可以接提示符

-t:后面可以接等待的秒数,不会一直等待用户

1
2
3
4
5
common@common-Aspire-4750:~$ read -p "请输入name:" -t 30 name    #提示符和等待
请输入name:my name
common@common-Aspire-4750:~$ echo $name
my name

 

2、declare和typeset,用来申明变量的属性

-a:申明数组(array)

-i:申明整数数字(integer)

-x:和export一样,申明环境变量

-r:将一个变量申明为只读,不可更改内容,也不能unset

1
2
3
4
5
6
7
common@common-Aspire-4750:~$ sum=100+300
common@common-Aspire-4750:~$ echo $sum
100+300
common@common-Aspire-4750:~$ declare -i sum=100+300 #申明为整数才能求和
common@common-Aspire-4750:~$ echo $sum
400

 

3.数组属性array

1
2
3
4
5
6
common@common-Aspire-4750:~$ name[1]=123
common@common-Aspire-4750:~$ name[2]=456
common@common-Aspire-4750:~$ name[3]=789
common@common-Aspire-4750:~$ echo ${name[1]}  #使用$()来读取
123

 

18. shell中的$,比如$@和$##

1
2
3
4
5
6
7
8
9
10
$0 Shell本身的文件名
$1~$n 添加到Shell的各参数值。$1是第1参数、$2是第2参数&hellip;
$$ Shell本身的PID(ProcessID)
$! Shell最后运行的后台Process的PID
$? 最后运行的命令的结束代码(返回值)
$- 使用Set命令设定的Flag一览
$* 所有参数列表。如"$*"用「"」括起来的情况、以"$1 $2 &hellip; $n"的形式输出所有数
$@ 所有参数列表。如"$@"用「"」括起来的情况、以"$1" "$2" &hellip; "$n" 的形式输出所有参数
$# 添加到Shell的参数个数

$# 参数的数量

$@ 参数的内容

比如test.sh

1
2
3
4
5
#!/bin/sh

echo "number:$#"
echo "argume:$@"

运行 ./test a b,输出

1
2
3
number:2
argume:a b

  

19. shell中的/dev/null,代表空设备文件#

参考:Linux Shell 1>/dev/null 2>&1 含义

1
2
3
4
5
6
7
8
9
> &nbsp;:代表重定向到哪里,例如:echo "123" > /home/123.txt
1 &nbsp;:表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于"1>/dev/null"
2 &nbsp;:表示stderr标准错误
&amp; &nbsp;:表示等同于的意思,2>&amp;1,表示2的输出重定向等同于1

1 > /dev/null 2>&amp;1&nbsp;语句含义:
1 > /dev/null : 首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,说白了就是不显示任何信息。
2>&amp;1 :接着,标准错误输出重定向(等同于)标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件

 

20. 获得文本中的最短行和最长行#

1
2
3
最短行:awk '(NR==1||length(min)>length()){min=$0}END{print min}' data.txt
最长行:awk '{if (length(max)<length()) max=$0}END{print max}' data.txt

  

21.Shift命令#

Shift命令运行一次,将会销毁一个输入参数,后面的参数前移,比如下面脚本

1
2
3
4
5
6
7
8
#!/bin/bash

while [ $# != 0 ]
do
echo "prama is $1,prama size is $#"
shift
done

输入参数是 a b c,运行一次shift,参数 a b c将会减少一个

1
2
3
4
5
./shift_test.sh a b c
prama is a,prama size is 3
prama is b,prama size is 2
prama is c,prama size is 1