shell——入门笔记

1、history

history命令与!符号有关

!! 上一条命令

!$ 上一条命令的最后一个参数

!n 执行history中的第n条命令

!字符 执行history中最近一条以指定字符开头的命令

 

2、通配符

和正则表达式不同,没有正则表达式强大,多用于通配文件名、路径

* 匹配0~n个字符

[abc] 匹配[]中任一字符

匹配1个字符

 

3、重定向

>filename 输出重定向 如:>filename 清空文件

>>filename 输出重定向 如:echo 'test' >>test.txt 追加test

<filename 输入重定向 如:mail -s "主题" name@qq.com <content.txt <filename相当于文件内容

2> 错误重定向 如:sh test.sh >log 2>&1,&1表示log且正常输出和异常输出不会相互覆盖

2>> 错误重定向

注意:2>&1,重定向符号前后不要有空格,否则可能会报错

 

4、管道

前面输出作为后边命令的输入

 

5、作业控制

ctrl + z 暂停

jobs 查看暂停的作业

fg n 回复指定作业

fg 恢复优先级高的,最后暂停的优先级高。类似栈,后进先出

ctrl+c 终止

 

6、自定义变量、全局变量、环境变量

自定义变量是在shell中直接定义的

全局变量是用export关键字声明的,可以用户当前shell及其子shell

环境变量是系统自动声明的全局变量

env 打印环境变量

set 打印全部变量

exprt 声明全局变量

unset 取消变量

bash/exit 进入/退出子shell

env | grep '^a' 打印全局变量中以a开头的

 

 

7、变量的定义

变量名由数字、字符、下下划线组成,不能以数字开头,一般不以下划线开头

变量赋值等号前后不能有空格

变量值可以不使用引号、使用单引号、双引号、反引号,在包含特殊字符时可能含义不同

 

不使用引号:使用[[ $a == a* ]]进行字符串通配符匹配时,可以表示模式

单引号 强制引用,引号内的特殊字符不会转义

双引号 引用,引号内的特殊字符可以转义,比如$a

反引号 引用结果,引用引号内容执行后的结果

shell中字符串可以直接连接,可以选择性使用引号引用需要进行连接的字符串

 

 

 

8、与环境变量相关的4个文件

 

用户登录时调用

进入子shell时调用

对任意用户有效

/etc/profile

/etc/bashrc

对当前用户有效

~/.bash_profile

~/.bahrc

4个文件间存在调用关系,比如profile文件经常调用bashrc文件

不同linux文件名可能不同,调用关系可能不同,甚至涉及到的不止这4个文件,可以查看具体代码确认

 

./bash_history 命令记录

./bash_logout 用户退出时执行

 

 

9、特殊符号

* 任意个任意字符

一个任意字符

[] 其中任意字符,如:[1234]

# 注释

\ 脱意,如:"\\" 输出 \\

| 管道

$ 表示变量

; 在一行写多条命令时,分隔命令

~ 家目录

& 连接命令,如:ls && cd /tmp

在后台执行命令,如:sleep 1000 &

表示输出文件,如:./test.sh 1>log 2>&1

> 重定向>> []

 

10、cut命令——分割

cut -d 分隔符 -f 区域 目标文件,如:cut -d ':' -f 1-3,4 /etc/passwd

cut -c 区域 目标文件,如:cut -c 1-3,4 /etc/passwd

-d:按照分隔符分割,且指定分隔符;-f:指定目标列

-c:按照字符分割,且指定目标列

 

11、sort命令——排序

sort -t 分隔符 -k 排序列 -nr 目标文件,如sort -t ':' -k 3 -nr /etc/passwd

-t:指定分隔符;-k指定按照第几列排序;-n指定按数字大小排序,默认按照ASCII排序;-r指定倒序排序,默认正序

sort常与cut命令结合使用,如:

sort -t ':' -k 3 -nr /etc/passwd | cut -d ':' -f 1

cut -d ':' -f 3 /etc/passwd | sort -n

遇到重复可以使用-u或者uniq -c,后者可以统计重复数量,如:

cut -d ':' -f 3 /etc/passwd | sort -n -u

cut -d ':' -f 3 /etc/passwd | sort -n | uniq -c

 

 

12、wc命令——文件内容统计

wc 目标文件,如:wc /etc/passwd

输出4个字段:行数、单词数、字符数、文件名

注意,被空白字符分割开,才会被识别为新单词;字符数包含换行符

常用wc -l 文件名,如:wc -l /etc/passwd

 

13、uniq -c

 

14、tee命令——输出

command | tee -a 输出文件,配合管道符号,将命令结果输出至标准输出的同时按照要求保存至指定文件,如:cat 1.txt | tee -a 1.log

不指定输出文件就只输出至标准输出,在命令行直接执行时,标准输出是屏幕直接打印

-a:追加,默认覆盖

>和>>命令的区别在于,>和>>是重定向,tee是不改变原有输出的情况下再输出一份内容

 

 

15、tr命令——替换

command | tr 原字符 新字符,配合管道符号,对命令结果进行字符替换,如:ls / | tr 'a-z' 'A-Z'

 

16、split命令——切割文件

split -l 行数 源文件 新文件名,文件按行数进行切割,如:split -l 10 /etc/passwd

split -b 大小 源文件 新文件名, 文件按大小进行切割,如:split -b 1M /etc/passwd

切割不会删除源文件

会自动为新文件名添加后缀,后缀貌似不能指定

 

17、&&和||和 ;

command1 && command2:command1成功执行后执行command2

command1 || command2:command1执行失败时执行command2

command1; command2:command1和command2的只有先后关系

 

 

18、shell中的正则

? 0个或1个问号前边的字符

+ 1个或n个加号前边的字符

* 任意个星号前边的字符

. 一个任意字符

.* 任意个任意字符

[a-zA-Z] 方括号中的字符之一

[^字符] 方括号中的字符以外

^ 以某字符开头

$ 以某字符结尾

^$ 空行

{次数} 指定次数前边的字符,在单引号表示的模式中,需要\符号转义

() 单元,将括号内作为一个整体,可以和?/+/*/{}等结合使用

| 或

[a|b] 表示a 或| 或b

 

? + {} () | - 这些符号在shell正则中属于扩展内容,可以使用egrep或grep -E或在模式中转义它们

 

 

19、grep命令

grep 模式 文件

显示文件中匹配模式的行,模式最好用单引号括起来

-c 统计匹配的行数

-n 显示行号

--color 高亮显示 alias grep='grep --color' 可以定义别名

-o 仅显示匹配的部分 grep -o 模式 文件 | wc -l 统计匹配次数

-v 显示不匹模式的行

-A 2 同时显示匹配行之后的两行

-B 2 同时显示匹配行之前的两行

-C 2 同时显示匹配行前两行和后两行

-r 对某目录下的文件进行grep操作,不确定是否会递归子目录下的文件

-q quite,静默模式,不输出任何结果,用于条件判断,成功匹配为真,没有成功匹配为假

两个过滤条件,可以使用管道符号grep两次

grep的输入可以是文件,也可以是重定向的内容,因此想要对字符串使用grep时,可以echo 字符串 | grep

 

 

 

 

20、sed命令:查找与替换

sed -n '特征p' 文件

打印指定行

特征可以使用 /正则模式/ 或行号,行号可以只用数字表示某一行,也可以表示某个区间如'1,10p'或'^,10'或'10,$'。使用正则时,某行含有匹配正则模式的内容,则认为该行匹配

p是print打印

-n表示静默模式,不使用-n会将全文打印,在遇到匹配特征的行时额外打印该行

sed无法显示行号和颜色,行号可以借助grep或其他命令,如:grep -n '.*' | sed '特征p' -n

当使用扩展部分的正则时,可以使用转义符号,或-r,如:sed -r '特征p' 文件 -n

 

sed -n -e '特征p' -e '另一个特征p' 文件 等同sed -n '特征p;另一个特征p' 文件

输出结果与使用正则中的|类似,但使用|在遇到一行匹配多个特征时,只打印一次,上边命令匹配到几个特征就重复打印几次,类似于shell命令中command1 || command2和command1;command2

 

p实际上是操作符,操作符除了p还有d(delete删除,删除行)

 

sed -r 's/模式/新字符串/g'

s表示替换;g表示遍历整行,否则每行只替换一项就开始下一行的替换;-r表示模式中扩展部分不需要转义

替换后内容不影响原内容,如果想修改原内容使用-i。也可以使用重定向,但重定向不支持重定向至自己

新字符串为空时,实际上为删除模式匹配的字符串

替换时不要使用-n选项,否则不会再屏幕上打印结果

 

 

21、awk

awk -F 分隔符 '{命令}' 文件

使用-F指定分隔符,默认分隔符为空白字符串

$0为整行,$n为分割后的第n个字符串

 

分割后匹配,如:awk -F ':' '$1~/root/ {print $2,$3}' /etc/passwd

单引号中的命令部分分为两部分,第一部分$1~/root/相当于if,第二部分相当于匹配成功后需要执行的命令。

使用~符号指定分割后的某个段与指定模式匹配,使用{print xxx}将需要的结果打印出来。不写{print xxx}默认为{print},即打印匹配项所在整行

 

替换分隔符,如:awk -F ':' '$1~/root/ {OFS="#";print $1,$2}' /etc/passwd

在条件成功后,输出时可以使用OFS指定分隔符,默认使用空格,指定分隔符时需要使用双引号,输出$0不会替换分隔符

 

精准匹配条件,如:awk -F ':' '$1=="root" || NR>30 {print $1,$2}' /etc/passwd

使用==表示精准匹配,注意不要写成=

可以使用||和&&表示条件的或和与

NR表示行号,和OFS类似,都是awk命令自定义的变量,另外NF表示分割后的段数

 

条件支持数字运算,如:awk -F ':' '$1=$3+$4 {OFS="#";print}' /etc/passwd

$3+$4后赋值给$1,使用$1进行条件判断,因为/etc/passwd的第一行运算后$1为0,所以第一行没有输出,这一点类似php,条件判断可以使用赋值语句,使用赋值后的结果进行判断。貌似仅限数字运算,字符串好像不行

$1发生变化后,$0发生变化,分隔符失效,需要重新指定分隔符,默认使用空格

 

22、shel脚本调试

sh -x script_name.sh

 

23、date

格式化字符串:

%Y 年,如:2017

%y 年,如:17

%m 月

%d 日

%H 时

%M 分

%S 秒

%w 本周第几天,如:6

%W 本年第几周,如:35

%F 完整日期,如:2017-09-02

%T 时间,如:10:25:12

%s 时间戳(秒)

 

格式化输出时间时,在格式化字符串前加+,如:date +'%F %T'。如果没有使用空格可以去掉引号

 

识别时间字符串:-d,如:date -d '2017-09-02 10:42:35'

可以相对智能的识别时间字符串,没有空白字符时可以去掉引号

使用@timestamp表示时间戳,注意时区问题

可以将识别出来的时间格式化输出

-d还可以识别时间偏移量(不知道如何对指定时间设置时间偏移量),如:date -d '+1 year'。可识别的偏移单位有year/month/day/hour/min/sec/week,偏移量可以是证书或者负数,可以多个偏移量同时出现

 

24、bc计算器

echo “365/7"|bc

 

25、变量

可以将命令直接定义为变量,使用命令时直接调用变量。

可以将命令执行结果定义为变量(反引号)

可以通过用户交互命令定义变量(read)

可以通过内置变量$0...$n,来引用当前脚本的脚本名、参数,使用$#引用参数的个数

 

26、read命令

在交互状态获取用户输入

read -p 提示字符串 变量1 变量2 ... 变量n

-p用于指定显示给用户的提示

定义几个变量就可以输入几个变量,输入时以空白字符隔开,多余定义变量数的输入将作为字符串赋值给最后一个变量

不定义变量可以使用$REPLY内置参数来引用输入

 

27、数学运算

i=1; j=2; k=$i+$j; echo $k

>1+2

因为shell中没有区分变量的类型,都是字符串,所以无法将$i+$j识别为数学运算,而是统一当做字符串连接,因此需要一些特殊的表示,告诉shell,我要做的是数学运算

方法一:$[]

i=1; j=2; k=$[$i+$j]; echo $k

>3

方法二:$(())

i=1; j=2; k=$(($i+$j)); echo $k

>3

i=1; j=2; ((k=$i+$j)); echo $k

>3

方法三:bc

以上两种不支持浮点数运算,bc可以

还不知道有什么区别

 

28、条件判断:if

shell中,没有布尔类型的变量,因此无法类似其他语言,将其他类型转换为布尔类型直接进行判断

有一个例外,字符“:”可以被if认为是真

shell中的条件判断语句有点复杂

数字比较判断:

在双括号中写表达式;

空格可有可无;

数字字符串会自动识别为数字。

如:

if (('1'=='1')); then echo 'true'; else echo 'false'; fi

>true

支持的操作符有:

==

!=

<

<=

>

>=

数字判断也支持在方括号中表示,但数字字符串与方括号和操作符间必须有空格,操作符需要使用对应的字符形式

如:

if [ '1' -eq '1' ]; then echo 'ok'; else echo 'not ok'; fi

>ok

相应的操作符为:

== -eq

!= -ne

< -lt

<= -le

> -gt

>= -ge

字符串比较判断:

在方括号或双方括号中写表达式;

方括号中,操作符“=”和操作符“==”等价,均为比较字符串是否匹配

双方括号仅支持操作符“==”,但支持字符串匹配和模式匹配(通配符)使用双引号时表示字符匹配,不适用双引号时表示模式匹配。如:

pattern=a*; if [[ 'ab' == $pattern ]]; then echo 'ok'; else echo 'not ok'; fi

>ok

pattern=a*; if [[ 'ab' == "$pattern" ]]; then echo 'ok'; else echo 'not ok'; fi

>not ok

字符串与方括号或双方括号或操作符间必须有空格

多个条件

可以使用“&&”操作符和“||”操作符连接完整的条件表达式,也可以使用操作符“-a”、操作符“-o”和操作符“!”在条件表达式内部对条件进行连接。

如:

num=5; if (($num>1)) && (($num<10)); then echo 'ok'; else echo 'not ok'; fi

>ok

num=5; if [ $num -gt 1 -a $num -lt 10 ]; then echo 'ok'; else echo 'not ok'; fi

>ok

 

一条命令也可以作为条件判断,命令执行成功为真,命令执行失败为假。因为不关心命令的输出,只关心命令是否成功执行, 所以可以将正常输出和异常输出都重定向至/dev/null,命令是否成功执行可以再命令行中通过$?查看,为0执行成功,为1执行失败。

如:

if ls /test/test/test >/dev/null 2>&1; then echo 'ok'; else echo 'not ok'; fi

>not ok

[ 1 -ne 1 ]; echo $?

>1

可以在命令行中测试条件,使用$?查看测试结果

 

29、exit

exit 0和exit 1都可以退出当前脚本,区别在于退出后调用$?分别返回0和1,一般认为返回0为正常结束,返回1为异常结束

 

30、文件判断

[ 选项 文件路径 ]

-e 文件存在

-f 文件存在且为普通文件

-d 文件存在且为目录

-r 文件存在且可读

-w 文件存在且可写

-x 文件存在且可执行

可以结合!取反

可以结合&&和||,根据条件决定后边的命令是否执行,类似if

 

31、exec

指定当前脚本中正常输出和异常输出的输出位置。如:

d=`date +%F`; exec >/tmp/$d.log 2>&1

以时间为文件名的日志输出

 

32、变量判断

[ 选项 变量 ]

-z 变量为空,如未赋值的变量,可以使用!取反

 

33、case循环

case 变量 in

取值1)

operation

;;

取值2|取值3)

operation

;;

*)

operation

;;

esac

匹配取值后无需退出,不会继续匹配

操作符“|”表示或

每个分支需要”;;“结尾

最后一个分支,用*匹配任意其他取值

最后需要esac结尾

 

33、seq

序列发生器,seq 起点 步进 终点,步进可以省略,默认为1,生成的序列,包含起点和终点

 

34、for循环

for i in 序列

do

operation

done

如:

for i in `seq 1 100`; do ((num+=$i));echo $num; done

数学运算中,为空的变量会被转换为0,因此未定义的变量是可以使用的

for f in `ls /etc/`; do if [ -d /etc/$f ]; then echo $f; fi; done

for i in 1 2 3 4 5; do echo $i; done

>1

>2

>3

>4

>5

可以看出来,for循环实际上是对in后边的字符串按照空白字符做了分割,上面的3个例子应该都是这个原理。注意,'1 2 3 4 5'和"1 2 3 4 5"会被作为一个整体,不会被分割。不明白使用引号的变量和不使用引号的变量到底有什么区别

 

因为行中可能有空白字符,因此按行输出直接for line in `cat 文件`是会出错的,可以使用sed。如:

n=`wc -l /etc/passwd|awk '{print $1}'`; for i in `seq 1 $n`; do sed -n "$i"p /etc/passwd; done

 

 

35、while循环

多用于配合操作符“:”写死循环。crontab最快1分钟循环一次,当频率需要更高时,只能用死循环

while :

do

operation

done

 

36、函数

input(){

echo $1

}

input liyh122

>liyh122

函数里的$n,指函数的参数,而不是脚本的参数

shell中的函数调用,直接写函数名即可,如果有参数,写在后边

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值