1、在linux里,如果直接在窗口执行: ./xxx
会默认将xxx文件当作脚本运行
2、使用 sh xxx 和使用 bash xxx 效果相同,因为这俩是软连接的关系
3、通常每个shell脚本中,第一行都有个 #! /bin/bash
这个是在告诉系统,这个脚本使用什么解释器
举个例子,如果是个python脚本,这里也可以定义python解释器: #! /usr/bin/python
然后下面就可以写python代码了
4、从规范的角度来说,脚本文件,应该带上相应的文件后缀,shell脚本应该明确写xx.sh,python文件明确写 xx.py
当然不写文件后缀,在文件内第一行加上 #!解释器 也ok
这里注意:./ 的方式执行脚本,是需要该文件拥有可执行权限的
bash xxx ,以这种方式执行文件,就等价于python xxx.py 的模式,就等于是指定了解释器,那么文件里第一行那个#!的代码就不再生效了。
5、linux中:history 可以查看命令的历史记录
6、alias,起别名, eg: alias aa="echo aa"
然后直接输入aa 就可以打印aa于控制台,当然直接在控制台输入alias 也可以查看当前有的别名,使用 unalias xx也可以取消别名,注意:自己添加的别名,重启设备后会消失
7、linux中,ctrl + c 是取消前台正在执行的程序,
ctrl + z是将前台正在执行的程序,放到后台执行
ctrl + y 粘贴或恢复上一次的删除
ctrl + k 清除光标后至行尾的内容
ctrl + u 清除光标前至行首的内容
ctrl + l 清屏 == clear
8、screen 这是一个linux的工具,可以用来保护执行环境。举例来说,如果在传输大文件,突然遇到网络中断或者断电,那么往往已经传输的那部分文件就没了,但是使用 screen 就可以保留文件,不会丢失这些东西。
用法:screen -S name # 给屏幕起一个名字
然后,就会默认进入这个屏幕,该干嘛干嘛
screen -ls 查看所有后台窗口,从中可以看到进程号,可以用来恢复窗口,也可以用来kill 进程号关闭进程干掉这个窗口
screen -r xxx_id 重新连接会话
ctrl + AD 挂起当前屏幕
9、输入输出重定向:>, >>, 1>, 2>>, &>, cat <
> :重定向,它可以创建文件,清空文件,写入文件
>> :追加文件内容
1> :标准输出, eg : ehco "hello world" 1>test1.txt
2 > : 错误输出, eg : ehc "hello world" 2>test1.txt
&> : 混合输出
cat < xxx.txt >aaa.txt : 先读取文件,再把读取的文件内容重定向
10、linux中的 | 也叫管道,将前者的标准输出内容,作为后者命令的标准输入内容
tee命令,是linux下的文件管理命令,它可以重标准输入设备读取数据,将其内容输出到标准输出设备,同时还能保存成文件。Eg: tee file1 file2 将内容同时保存到file1,file2,注意这种事覆盖式的, tee -a file1 追加式保存内容
11、命令执行顺序:
; 命令用 ';' 连接,命令与命令之前无关系,就是跟手动一条一条的执行命令是一样的
&& 命令用 '&&' 连接,命令与命令存在逻辑联系,前面的命令执行成功,后面的命令才会执行
|| 命令用 '||' 连接,命令与命令存在逻辑联系,前面的命令执行不成功,后面的命令才会执行
单独命令后 + & ,就是将这条命令放到后台执行
12、在命令行,执行命令的时候,用 ( ),将命令括起来,代表使用子shell去执行命令,就相当于重新开一个窗口去执行命令,完了后关闭窗口,并将结果反馈到当前shell,它的好处就是,它不会改变当前窗口的环境。
13、{} 集合, eg:touch file{1,9}, 结果就是创建 file1, …,file9
14、 echo -e "\033[30m黑色字\033[0m"
echo -e "\033[31m红色字\033[0m"
echo -e "\033[32m绿色字\033[0m"
echo -e "\033[33m黄色字\033[0m"
echo -e "\033[34m蓝色字\033[0m"
echo -e "\033[35m紫色字\033[0m"
echo -e "\033[36m天蓝字\033[0m"
echo -e "\033[37m白色字\033[0m"
注意,在一些文档看的时候,这里需要加 -e 参数,但是我在自己的虚拟机上测试的时候,并不需要加 -e,加了-e,反而多了个-e
15、linux中调用变量时, $xx 和 ${xx} ,其作用是一样的,都是在调用变量。但是对于${xx}aaaaa,这样的场景,不加大括号,就无法调用变量xx。
16、对于在terminal中的自定义变量只在当前窗口和子shell中生效。
17、linux中的 source xxx 命令,有点像python中的import的意思,就是导入的意思
18、linux 中 $? ,查看上一个命令执行的结果。
19、/etc/profile 是linux配置文件,一般可以给里面添加全局变量
20、sh xxx.sh a b c 这是说,在执行xxx.sh文件的时候传入参数a,b,c,在xxx.sh中,可以使用 $1, $2, $3,来获取这些位置参数,这些位置参数,最多可以传10个,对应$1 ~${10}
21、shell的交互模式,read -p "提示语:" paramer_name eg: read -p "请输入姓名:" name,name这个参数负责绑定你的输入内容
也可以 read -t 5 -p "sss" paramer_name 加了 -t 5 就是等待5秒的意思
注意:这里一次性可以给多个参数
22、预见定义变量:
$0 :脚本名称
$* : 所有参数
$@ : 所有参数
$# : 参数个数
$$ : 当前进程PID
$! : 上一个进程的PID
$? : 上一条命令的返回值
23、basename 这条命令本身也是一个linux的命令,通常我们可以在shell中这么用: $(basename $0)
24、`date +%F` 和 $(date +%F) 是一样的,获取当前时间,年-月-日,注意,shell中,更推荐使用$()的方式添加命令。因为这种方式看起来更清晰。
25、linux中的强引用和弱引用,单引号为强引用,所见即所得,双引号为弱引用,会对内容进行解析。所以,通常如果你需要输出特殊字符,就用单引号,不要用双引号,因为双引号有可能会报错的。
26、expr $a + $b 可以进行数学运算,+ , - , \*, / 加减乘除
$(( $a + $b )) 作用同上
$[ $a + $b ] 作用同上
let sum=$a + $b 作用同上 注意:以上方法均为整数运算方式
27、小数运算 bc,bc是个linux的工具,是可以下载的。
用法:echo "2*7" | bc
echo "scale=2;6/4" | bc 注意,scale是指定小数点后位数的,不给默认就是0
28、${xxx-aaa} 这是给参数添加默认值的写法,就是说xxx如果赋值了,就是使用它自己的值,没赋值就用默认值aaa。注意:如果xxx赋值空,那么输出也就是空,不会走默认值的
29、${xxx:-aaa} 这里多了一个 “:”,于28的区别在于,它会判空,如果xxx赋值为空,那就走默认值
30、linux自增运算,++i 和 i++的区别就是,++i是先运算,再赋值,i++是先赋值再运算
31、test 在linux中是个命令。用法:test 表达式
Eg: test -d /dump 判断 /dump 是不是文件夹
test -f xxx 判断 xxx 是否存在,是不是文件
test -r xxx 判断xxx是不是有可读权限
test -x xxx
test -w xxx
test -e xxx 判断文件是否存在
32、经常在 if [ … ];fi ,注意,中括号[], 这玩意儿是个命令。
33、awk
awk -F, 'BEGIN{print "hahaha"}{print $2}END{print "结束啦"}' xx.txt 这是awk的标准模式,读取文件之前干啥,读取文件干啥,读完文件干啥,
-F指定分割列时用的分割符
awk 'NR>=1 && NR<=5' xx.txt 打印1-5行,NR是number of record 行号的意思
column -t 将列显示的好看点,对齐
awk '{print $1,$NF}' xxx.txt 打印第一列和最后一列。NF是number of field 总列数的意思
awk -F: -v OFS '{print $1,$2}' xxx.txt 将:作为列的分割符,并最后输出 -F== -v FS , -v OFS F: Field S: separator O: output
awk -F: '$3~/^1/' xx.txt 文件中第三列中包含以1为开头的东西。 ~ 代表包含,!~代表不包含
awk '/11:02:00/,/11.05.00/{print $1}' xx.txt 显示11:02:00到11.05.00这个时间段的数据的第一列
seq 100 | awk 'BEGIN{i=0}{i+=1}END{print i}' awk的计数模式,如果i的初始值默认就是0,所以,如果定义的值为0,也可不定义
seq 100 | awk 'BEGIN{i=20}{i+=1}END{print i}' 定义初始值为i=20
seq 100 | awk 'BEGIN{sum=0}{sum+=$1}END{print sum}' 求和模式,同样sum的默认值为0,所以这里也可不定义begin
seq 100 | awk 'BEGIN{sum=0}{sum+=$1;print sum}END{print sum}' 多了个print可以打印加和的过程,这里一定注意,中间的花括号里,一定用的是 :而不是','
seq 100 | awk 'BEGIN{sum=0;a=1}{sum+=$1;print sum}END{print sum, a}' 注意语句,一个语句内是','分隔,多个语句是';'分隔
awk 'BEGIN{a[0]=1;a[1]="ymk"; for (i in a) print i, a[i]}' 这里的for语句是awk专用的,for里取的是数组下标
awk -F"[/]" '{a[$3]++}END{for (i in a) print i,a[i]}' test2 这里 a[]++ 就是用来搞统计的,[]里填要统计的列
awk -F"[/]" '{a[$3]++}END{for (i in a) print i,a[i]}' test2 | sort -rnk2 顺便排序,-r是逆序,n是数字,k代表列,2就是第二列
echo you are aaaaacd a good baby bbbbbb. | awk -F"[ \.]" '{for (i=1;i<=NF;i++) if (length($i)<4) print $i}'
注意,shell中换行的写法为 echo -e "\n"
awk -F '[G ]+' '{print $1}',这里跟上面 -F 的区别是,这里使用了正则,[G ]+ ,意思是一个或多个G和空格
34、echo {1..10} 输出为 1,2, 3,…,10,这里注意,如果在shell脚本中写 for 循环,如:for num in {1..10};do done
这样写是没问题的,但是如果搞成参数的话就不行了。如:for num in {1..$xxx};do done,这种就无法迭代了。
这种带参数的情况就需要使用seq,如:for num in $(seq $xxx);do done
35、shell中的条件测试,有三种:
test 条件表单式 这种上面有介绍
[ 条件表单式 ] 这种主要用到 if,while 等条件语句的
[[ 条件表单式 ]] 这种主要用于字符串比对的 eg: if [[ ! $user =~ ^[a-Z]+$ ]];then fi
36、cat > /etc/yum.repos.d/nginx.repo <<-EOF
[niginx]
name=nginx repo
baseurl=http://.....
EOF
注意:这里的cat> xx <<-EOF ,这种写法后面可以直接跟要写的文件内容,完事后加个EOF,表示写完了。
37、并发的场景,之前有个命令 &,(cmd)&,就可以将cmd放到后台执行,这样就可以实现并发执行一些较为耗时的命令。
38、按行读取文件内容。
while read line
do
echo "$line"
done<xxx.txt
39、交互式语言expect,在shell中的使用:
while read line
do
/user/bin/expect <<-EOF
set timeout 5
spawn cmd_xxx
expect {
"aaa/no" { send "aaa\r"; exp_continue}
}
expect eof
EOF
echo "$line"
done<xxx.txt
40、sh -n xx.sh 注意, -n 可以判断shell中是否存在语法错误
sh -x xx.sh 注意, -x 可以打印执行过程
sh -vx xx.sh 注意, -x 可以打印执行过程 -v 是相当于debug模式
41、for I in $(cat xxx.txt)
do
done
这样的方式可以从文件中,按行读取内容
其实还有一种方法:for i in *aaa.txt* ,这种好像也可以,在其他地方见过这种写法
42、while : 这等价于 while true
43、shell中的数组,跟python中的字典是一个性质。
declare -A tt_array_1 声明一个关联数组 tt_array_1
tt_array_1[name]=aaa
tt_array_1[age]=18
以key,value的方式进行关联数组赋值
echo ${tt_array_1[name]} 取值
echo ${tt_array_1[*]} 取所有的value
echo ${tt_array_1[@]} 取所有的value
echo ${ ! tt_array_1[@]} 取所有的key
也可以一把定义完整个数组:
tt_array_1=([key1]=value1 [key2]=value2 [key3]=value3)
declare -A 查看关联数组
44、linux中sort命令,可以用来排序
添加参数 -r 是反序
添加参数 -k 是指定第几列为依据排序
45、linux中uniq 这个命令读取输入文件,并比较相邻的行
– c 显示输出中,在每行行首加上本行在文件中出现的次数。它可取代- u和- d选项。
– d 只显示重复行。
– u 只显示文件中不重复的各行。
46、函数的定义:
47、shell中函数的返回值,只能是数字,通常用来表示成功与否
48、if [ 1 -gt $aa -a 2 lt $bb ] ;then fi 这里 -a 表示与的意思
49、shell中函数的传参,模式跟shell脚本的传参形式很类似
就是函数名后面跟参数,以空格隔开(这跟脚本调用时的传参,简直一模一样),函数内部对参数的使用,也是$1, $2 ,…, $n ,以这样的方式来获取,传入给函数的参数
50、正则中 [abc] ,代表匹配中括号中的任意字符
正则中 [^abc] ,代表匹配除了中括号中的字符以外的任意字符
正则中 ^$,表示空格
grep -vn "^$" aaa.txt 显示aaa.txt中除了空行以外的内容(代行号)
注意: -v 代表排除 n 代表行号
grep "." aaa.txt 匹配所有字符,但不包含空行
grep ".*" aaa.txt 匹配所有字符,包含空行
grep -o "8*" aaa.txt 匹配一个8或者多个8,其中 -o 代表只显示具体的结果,不带 -o,就会显示所有内容,只不过匹配到的内容会遍红
grep -E "8{2}" 或 egrep "8{2}" 或 grep "8\{2\}" 这三种写法是一回事 E ,e的作用是拓展正则的意思。
grep "ab(c|d)" aaa.txt 匹配 abc 或 abd
52、linux中的sed,它是一个流编辑器,非交互编辑器,它一次处理一行内容。处理时,当前处理的行,存储在临时缓冲区,也叫“模式空间”(pattern space),接着用 sed 命令处理缓冲区的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,周而复始,直至文件末尾。在这个过程,文件内容本身是没有改变的,除非使用重定向存储输出。
命令格式:
sed [options] 'cmd ' file(s) 注意:它个grep不同,不管是否找到指定模式,退出状态都是0,除非存在语法错误,返回值不为0
sed 命令,可以对执行的行进行各种操作,包括,打印,删除,修改,追加等。
options:
-e 允许多项编辑
-n 取消默认输出
-i 直接修改对应的文件
-r 支持扩展元字符
例子:
sed -n '2p' aaa.txt 只打印 aaa.txt 中的第二行(默认是打印所有内容,-n 取消默认输出)
cmd:
a 在当前行后,添加一行
c 用新文本修改(替换)当前行中的文本
d 删除行
i 在当前行之前,插入文本
p 打印匹配到的内容
n 读入下一行,并从下一条命令进行处理
! 对所选行以外的所有行,应用命令
s 替换 替换掉匹配的内容
例子:
sed -n '/asd/p' aaa.txt 匹配 asd ,然后打印匹配到的行
sed -n '$p' aaa.txt 打印文件中的最后一行
sed '/123/ahello' 1.txt #向内容123后面添加hello,如果文件中有多行包括123,则每一行后面都会添加
sed '$ahello' 1.txt #在最后一行添加hello
sed '3ihello' 1.txt #在第三行之前插入hello
sed '/123/ihello' 1.txt #在包含123的行之前插入hello,如果有多行包含123,则包含123的每一行之前都会插入hello
sed '$ihello' 1.txt #在最后一行之前插入hello
sed '1chello' 1.txt #将文件1.txt的第一行替换为hello
sed '4d' 1.txt #删除第四行
sed '1~2d' 1.txt #从第一行开始删除,每隔2行就删掉一行,即删除奇数行
sed '1,2d' 1.txt #删除1~2行
sed '1,2!d' 1.txt #删除1~2之外的所有行
sed '/123/d' 1.txt #删除匹配123的行
sed '/123/,$d' 1.txt #删除从匹配123的行到最后一行
sed '/123/,+1d' 1.txt #删除匹配123的行及其后面一行
sed '/^$/d' 1.txt #删除空行
sed '/123\|abc/!d' 1.txt #删除不匹配123或abc的行,/123\|abc/ 表示匹配123或abc ,!表示取反
sed '1,3{/123/d}' 1.txt #删除1~3行中,匹配内容123的行,1,3表示匹配1~3行,{/123/d}表示删除匹配123的行
sed 's/^/#&/g' 1.txt #在1.txt文件中的每一行开头加一个#,g是所有的意思
sed 's/123/hello/' 1.txt #将文件中的123替换为hello,默认只替换每行第一个123
sed 's/123/hello/g' 1.txt #将文本中所有的123都替换为hello
sed 's/123/hello/2' 1.txt #将每行中第二个匹配的123替换为hello
sed -n 's/123/hello/gpw 2.txt' 1.txt #将每行中所有匹配的123替换为hello,并将替换后的内容写入2.txt
sed '/#/s/,.*//g' 1.txt #匹配有#号的行,替换匹配行中逗号后的所有内容为空 (,.*)表示逗号后的所又内容
sed 's/^#.*//;/^$/d' 1.txt #先替换1.txt文件中所有注释的空行为空行,然后删除空行
sed 's/^[0-9]/(&)/' 1.txt #将每一行中行首的数字加上一个小括号 (^[0-9])表示行首是数字,&符号代表匹配的内容
sed 's/$/&'haha'/' 1.txt # 在1.txt文件的每一行后面加上"haha"字段
sed -n '2~2p' 1.txt #从第二行开始,每隔两行打印一行,波浪号后面的2表示步长
sed -n "$=" 1.txt #打印1.txt文件最后一行的行号(即文件有多少行,和wc -l 功能类似)
sed -n '/error/=' 1.txt #打印匹配error的行的行号
sed -n '/error/{=;p}' 1.txt #打印匹配error的行的行号和内容(可用于查看日志中有error的行及其内容)
sed 'r 2.txt' 1.txt #将文件2.txt中的内容,读入1.txt中,会在1.txt中的每一行后都读入2.txt的内容
sed '3r 2.txt' 1.txt #在1.txt的第3行之后插入文件2.txt的内容(可用于向文件中插入内容)
sed -n 'w 2.txt' 1.txt #将1.txt文件的内容写入2.txt文件,如果2.txt文件不存在则创建,如果2.txt存在则覆盖之前的内容
sed -n '2w 2.txt' 1.txt #将文件1.txt中的第2行内容写入到文件2.txt
sed -n -e '1w 2.txt' -e '$w 2.txt' 1.txt #将1.txt的第1行和最后一行内容写入2.txt
sed -n -e '1w 2.txt' -e '$w 3.txt' 1.txt #将1.txt的第1行和最后一行分别写入2.txt和3.txt
注意:以上内容,的所有改变,由于没有加 -i 参数,所以都是预览模式,都没有对文件本身做任何改变。
sed -n "3p" xx.txt 打印xx.txt文件里的第三行,-n的意思是,不将模式空间里的数据流打印到terminal,
sed -nr '/[0-9]+/p' 注意 sed默认不支持正则的拓展模式, 所以在使用 + 这种正则符号的时候,需要加 -r
sed -nr "3d" xx.txt 这里p是打印,那么d就是删除了,跟p的用法完全相同
sed -nr '/^$|#/!p' xxx.txt 遇到空行或带#的行,不打印。!代表取反,不的意思。
sed -r 's#(.*)#<\1>#g' xxx.txt 将每一行的内容左右加上<>.其中的()就是正则里组的意思,叫先保护再使用
sed -inr '/.*abc.*/s#.*#aa#' test2 一定记住,加了-i参数,就是真的把源文件改了,否则就只是预览模式,随便搞
53、tail -n2 aaa.txt 输出aaa.txt中的倒数2行
54、
#!/bin/bash
if [ $# -ne 2 ];then #判断位置变量的个数是是否为2
echo "Usage:$0 old-file new-file"
exit
fi
for file in `ls` #在当前目录中遍历文件
do
if [[ $file =~ $1$ ]];then #对用户给出的位置变量$1进行正则匹配,$1$表示匹配以变量$1的值为结尾的文件
echo $file #将匹配项输出到屏幕进行确认
new=${file%$1} #对文件进行去尾处理,去掉文件后缀保留文件名,并将文件名赋给变量new
mv $file ${new}$2 #将匹配文件重命名为:文件名+新的后缀名
fi
done
55、linux中, -z 和 -n 都是用来判断参数是否为空的, -z 是想要空,为空返回值为0,非空为1, -n 与之相反,使用的时候,如果是 [ -z "$aa" ] ,就需要加双引号,如果是 [[ -z $aa ]] 就不需要加引号
56、关于 # ,与%的区别:
57、关于 tr 的使用:
其次,可以参考这个命令:
echo 'a b c'|tr ' ' '\n'| awk '{print "--exclude " $$0}'
看下使用效果:
ymengkai@ubuntu:~/p4/stage-1/statusweb$ echo 'a b c'|tr ' ' '\n'| awk '{print "--exclude " $0}'
--exclude a
--exclude b
--exclude c
根据后来的再学习,其实,对于不了解 tr 的用法,完全不慌:
echo 'a b c' | sed -n 's# #\n#gp'| awk '{print "--exculde " $0}'
或
echo 'a b c' | sed -n 's# #\n#gp'| awk '{print "--exculde " $1}'
直接使用 sed ,完全 ok .