Shell操作使用技巧

  1. Shell操作日期时间
date :显示系统当前时间
date ' + %Y-%m-%d %H:%M:%S' :以指定的格式显示时间
date -s "2017-01-01 01:01" :设置系统时间
获取某个时间用-d
## 获取下一天的时间
[[email protected] ~]# date -d next-day '+%Y-%m-%d %H:%M:%S'
[[email protected] ~]# date -d 'next day' '+%Y-%m-%d %H:%M:%S'
另外一种写法:
[[email protected] ~]# date '+%Y-%m-%d %H:%M:%S' -d tomorrow

## 获取上一天的时间
[[email protected] ~]# date -d last-day '+%Y-%m-%d %H:%M:%S'
另外一种写法:
[[email protected] ~]# date '+%Y-%m-%d %H:%M:%S' -d yesterday

## 获取下一月的时间
[[email protected]hadoop ~]# date -d next-month '+%Y-%m-%d %H:%M:%S'

## 获取上一月的时间
[[email protected] ~]# date -d last-month '+%Y-%m-%d %H:%M:%S'

## 获取下一年的时间
[[email protected] ~]# date -d next-year '+%Y-%m-%d %H:%M:%S'

## 获取上一年的时间
[[email protected] ~]# date -d last-year '+%Y-%m-%d %H:%M:%S'

## 获取上一周的日期时间:
[[email protected] ~]# date -d next-week '+%Y-%m-%d %H:%M:%S'
[[email protected] ~]# date -d next-monday '+%Y-%m-%d %H:%M:%S'
[[email protected] ~]# date -d next-thursday '+%Y-%m-%d %H:%M:%S'

## 获取一天以后的日期时间
[[email protected] ~]# date '+%Y-%m-%d %H:%M:%S' --date='1 day'
[[email protected] ~]# date '+%Y-%m-%d %H:%M:%S' --date='-1 day ago'

## 获取一天以前的日期时间
[[email protected] ~]# date '+%Y-%m-%d %H:%M:%S' --date='-1 day'
[[email protected] ~]# date '+%Y-%m-%d %H:%M:%S' --date='1 day ago'

  1. 高级文本处理命令
    1. wc
功能:统计 文件行数 字节 字符数
常用选项:
-c: 统计文件字节数,一个英文字母 1 字节,一个汉字占 2-4 字节(根据编码)
-m :统计文件字符数,一个英文字母 1 字符,一个汉字占 1 个字符
-l :统计多少行
-L :统计最长行的长度, 也可以统计字符串长度
-w :统计字数
-help :显示帮助信息
--version :显示版本信息

  1. sort
功能:排序文本,默认对整列有效
常用选项:
-f :忽略字母大小写,就是将小写字母视为大写字母排序
-M :根据月份比较,比如 JAN、DEC
-h :根据易读的单位大小比较,比如 2K、1G
-g :按照常规数值排序
-n 根据字符串数值比较
-r 倒序排序
-k 位置 1,位置 2 根据关键字排序,在从第位置 1 开始,位置 2 结束
-t :指定分隔符
-u :去重重复行
-o :将结果写入文件
常用 -nk 组合, -r 常用

  1. uniq
功能:去除重复行, 只会统计相邻
常用选项:
-c :打印出现的次数
-d :只打印重复行
-u :只打印不重复行
-D :只打印重复行,并且把所有重复行打印出来
-f N:比较时跳过前 N 列
-i :忽略大小写
-s N:比较时跳过前 N 个字符
-w N:对每行第 N 个字符以后内容不做比较

  1. cut
功能:从一个文本文件或者文本流中提取文本列
语法:
cut -d'分隔字符' -f fields ## 用于有特定分隔字符
cut -c 字符区间 ## 用于排列整齐的信息
常用选项:
-d:后面接分隔字符。与 -f 一起使用
-f:依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思
-c:按照字符截取
-b:按照字节截取

  1. grep(文本生成器)
功能:文本搜索工具,能使用正则表达式搜索文本并统计匹配的行
语法:
grep [选项] [–color=auto] ”搜索字符串” filename
常用参数:
-c:统计符合条件的字符串出现的总行数。
-E:支持扩展正则表达式。
-i:忽略字符大小写。
-n:在显示匹配到的字符串前面加上行号。
-v:显示没有”搜索字符串”内容的那一行。
-l:列出文件内容中有搜索字符串的文件名称。
-o:只输出文件中匹配到的部分。
-color=auto:将匹配到的字符串高亮出来。

正则表达式的简单规则:
. : 任意一个字符
a* : 任意多个 a(零个或多个 a)
a? : 零个或一个 a
a+ : 一个或多个 a
.* : 任意多个任意字符
\. : 转义.
o\{2\} : o 重复两次
[A-Z]
[ABC]

  1. sed(流编辑器)
功能:sed 是一种在线编辑器,它一次处理一行内容,处理时,把当前处理的行存储在临时缓冲区中,称为"模式空间",接着用 sed 命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
常用选项:
-n:一般 sed 命令会把所有数据都输出到屏幕,如果加入-n 选项的话,则只会把经过 sed 命令处理的行输出到屏幕。
-e:允许对输入数据应用多条 sed 命令编辑。
-i:用 sed 的修改结果直接修改读取数据的文件,而不是由屏幕输出。

d:删除
a:追加,在当前行后添加一行或多行。
c:行替换,用 c 后面的字符串替换原数据行。
i:插入,在当前行前插入一行或多行。
p:打印,输出指定的行。
s:字符串替换,用一个字符串替换另外一个字符串。格式为'行范围 s/旧字符串/新字符串/g'(如果不加 g 的话,则表示只替换每行第一个匹配的串)

1 、删除:d 命令
sed '2d' sed.txt -----删除 sed.txt 文件的第二行。
sed '2,$d' sed.txt -----删除 sed.txt 文件的第二行到末尾所有行。
sed '$d' sed.txt -----删除 sed.txt 文件的最后一行。
sed '/test/d ' sed.txt -----删除 sed.txt 文件所有包含 test 的行。
sed '/[A-Za-z]/d ' sed.txt -----删除 sed.txt 文件所有包含字母的行。
2 、 整 行替换:c 命令
将第二行替换成 hello world
sed '2c hello world' sed.txt
3 、 字符串 替换:s 命令
sed 's/hello/hi/g' sed.txt
## 在整行范围内把 hello 替换为 hi。如果没有 g 标记,则只有每行第一个匹配的 hello 被替
换成 hi。
sed 's/hello/hi/2' sed.txt
## 此种写法表示只替换每行的第 2 个 hello 为 hi
sed 's/hello/hi/2g' sed.txt
## 此种写法表示只替换每行的第 2 个以后的 hello 为 hi(包括第 2 个)
sed -n 's/^hello/hi/p' sed.txt
## (-n) 选项和 p 标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头
的 hello 被替换成 hi,就打印它。
sed -n '2,4p' sed.txt
## 打印输出 sed.txt 中的第 2 行和第 4 行
sed -n 's/hello/&-hi/gp' sed.txt
sed 's/^192.168.0.1/&-localhost/' sed.txt
sed 's/^192.168.0.1/[&]/' sed.txt
## &符号表示追加一个串到找到的串后。所有以 192.168.0.1 开头的行都会被替换成它自已
加 -localhost,变成 192.168.0.1-localhost。第三句表示给 IP 地址添加中括号
sed -n 's/\(liu\)jialing/\1tao/p' sed.txt
sed -n 's/\(liu\)jia\(ling\)/\1tao\2ss/p' sed.txt
## liu 被标记为\1,所以 liu 会被保留下来(\1 == liu)
## ling 被标记为\2,所以 ling 也会被保留下来(\2 == ling)
## 所以最后的结果就是\1tao\2ss == "liu" + "tao" + "ling" + "ss"
此处切记:\1 代表的是被第一个()包含的内容,\1 代表的是被第一个()包含的内容,……
上面命令的意思就是:被括号包含的字符串会保留下来,然后跟其他的字符串比如 tao 和 ss
组成新的字符串 liutaolingss
sed 's#hello#hi#g' sed.txt
## 不论什么字符,紧跟着 s 命令的都被认为是新的分隔符,所以,"#"在这里是分隔符,
代替了默认的"/"分隔符。表示把所有 hello 替换成 hi。
选定行的范围:逗号
sed -n '/today/,/hello/p' sed.txt
## 所有在模板 today 和 hello 所确定的范围内的行都被打印。都找第一个,也就是说,从第
一个 today 到第一个 hello
sed -n '5,/^hello/p' sed.txt
sed -n '/^hello/,8p' sed.txt
## 打印从第五行开始到第一个包含以 hello 开始的行之间的所有行。
sed '/today/,/hello/s/$/www/' sed.txt
## 对于模板 today 和 hello 之间的行,每行的末尾用字符串 www 替换。
sed '/today/,/hello/s/^/www/' sed.txt
## 对于模板 today 和 hello 之间的行,每行的开头用字符串 www 替换。
sed '/^[A-Za-z]/s/5/five/g' sed.txt
## 将以字母开头的行中的数字 5 替换成 five
4 、 多点编辑:e 命令
sed -e '1,5d' -e 's/hello/hi/' sed.txt
## (-e)选项允许在同一行里执行多条命令。如例子所示,第一条命令删除 1 至 5 行,第二
条命令用 hello 替换 hi。命令的执行顺序对结果有影响。如果两个命令都是替换命令,那么
第一个替换命令将影响第二个替换命令的结果。
sed --expression='s/hello/hi/' --expression='/today/d' sed.txt
## 一个比-e 更好的命令是--expression。它能给 sed 表达式赋值。
5 、从文件读入:r 命令
sed '/hello/r file' sed.txt
## file 里的内容被读进来,显示在与 hello 匹配的行下面,如果匹配多行,则 file 的内容将
显示在所有匹配行的下面。
6 、写入文件:w 命令
sed -n '/hello/w file' sed.txt
## 在 huangbo.txt 中所有包含 hello 的行都被写入 file 里。
7 、追加命令:a 命令
sed '/^hello/a\\--->this is a example' sed.txt
## '--->this is a example'被追加到以 hello 开头的行(另起一行)后面,sed 要求命令 a 后面有
一个反斜杠。
8 、插入:i 命令
sed '/will/i\\some thing new -------------------------' sed.txt
## 如果 test 被匹配,则把反斜杠后面的文本插入到匹配行的前面。
9 、下一个:n 命令
sed '/hello/{n; s/aa/bb/;}' sed.txt 替换 下一行的 第一个 aa
sed '/hello/{n; s/aa/bb/g;}' sed.txt 替换下一行的全部 aa
## 如果 hello 被匹配,则移动到匹配行的下一行,替换这一行的 aa,变为 bb,并打印该行,
然后继续。
10 、退出:q 命令
sed '10q' sed.txt
## 打印完第 10 行后,退出 sed。
同样的写法:
sed -n '1,10p ' sed.txt

  1. awk(报表生成器)
功能:处理文本的编程语言工具
常见内置变量:
FILENAME:awk 浏览的文件名
FNR:浏览文件的记录数,也就是行数。awk 是以行为单位处理的,所以每行就是一个记录
NR:awk 读取文件每行内容时的行号
NF:浏览记录的域的个数。可以用它来输出最后一个域
FS:设置输入域分隔符,等价于命令行-F 选项
OFS:输出域分隔符

1、假设 last -n 5 的输出如下:
[[email protected] ~]# last -n 5
root pts/0 192.168.123.1 Wed Dec 28 01:55 still logged in
reboot system boot 2.6.32-573.el6.x Tue Dec 27 04:25 - 03:11 (22:46)
root pts/1 192.168.123.1 Tue Dec 27 02:00 - 02:00 (00:00)
root pts/1 192.168.123.1 Tue Dec 27 01:59 - 02:00 (00:00)
root pts/0 192.168.123.1 Tue Dec 27 01:59 - down (00:16)
2、只显示五个最近登录的账号:
[[email protected] ~]# last -n 5 | awk '{print $1}'
root
reboot
root
root
root
awk 工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符
划分域,填充域,$0 则表示所有域,$1 表示第一个域,$n 表示第 n 个域。默认域分隔符是"空
白键" 或 "[tab]键",所以$1 表示登录用户,$3 表示登录用户 ip,以此类推
3、显示/etc/passwd 的账户:
[[email protected] ~]# cat /etc/passwd |awk -F ':' '{print $1}'
root
bin
daemon
adm
lp
这种是 awk+action 的示例,每行都会执行 action{print $1}。
-F 指定域分隔符为':'
4、显示/etc/passwd 的账户和账户对应的 shell,而账户与 shell 之间以 tab 键分割
[[email protected] ~]# cat /etc/passwd |awk -F ':' '{print $1"\t"$7}'
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
5 、BEGIN and END
如果只是显示/etc/passwd 的账户和账户对应的 shell,而账户与 shell 之间以逗号分割,而且在
所有行添加列名 name,shell,在最后一行添加"blue,/bin/nosh"。
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print
"blue,/bin/nosh"}'
cat /etc/passwd | awk -F ':' 'BEGIN {print "name \t shell"} {print$1"\t"$7} END {print
"blue,/bin/bash"}'
name,shell
root,/bin/bash
daemon,/bin/sh
....
blue,/bin/nosh
awk 工作流程是这样的:先执行 BEGIN,然后读取文件,读入有/n 换行符分割的一条记录,
然后将记录按指定的域分隔符划分域,填充域,$0 则表示所有域,$1 表示第一个域,$n 表示
第 n 个域,随后开始执行模式所对应的动作 action。接着开始读入第二条记录• • • • • •直到所有的记
录都读完,最后执行 END 操作。
6 、 搜索/etc/passwd 有 有 root 关键字的所有行
awk -F: '/root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,
默认输出每行的内容)。
搜索支持正则,例如找 root 开头的: awk -F: '/^root/' /etc/passwd
搜索/etc/passwd 有 root 关键字的所有行,并显示对应的 shell
awk -F ':' '/root/{print $7}' /etc/passwd
/bin/bash
这里指定了 action{print $7}
6 、 awk 常见内置变量
FILENAME:awk 浏览的文件名
FNR:浏览文件的记录数,也就是行数。awk 是以行为单位处理的,所以每行就是一个记录
NR:awk 读取文件每行内容时的行号
NF:浏览记录的域的个数。可以用它来输出最后一个域
FS:设置输入域分隔符,等价于命令行-F 选项
OFS:输出域分隔符
统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容
awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF
",linecontent:"$0}' /etc/passwd
awk -F':' '{print "filename:" FILENAME ",linenumber:" NR ",colums:" NF "linecotent:" $0}'
/etc/passwd
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/bin/sh
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/bin/sh
使用 printf 替代 print,可以让代码更加简洁,易读
awk -F ':'
'{printf("filename:%s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}'
/etc/passwd
指定输入分隔符,指定输出分隔符:
awk 'BEGIN {FS=":"; OFS="\t"} {print $1, $2}' /etc/passwd
sshd x
tcpdump x
linux x

  1. find
功能:搜索文件目录层次结构
语法:
find path -option actions
find < 路径> < 选项> [ 表达式]
常用可选项:
-name 根据文件名查找,支持('* ' , '? ')
-type 根据文件类型查找(f-普通文件,c-字符设备文件,b-块设备文件,l-链接文件,d-目录)
-perm 根据文件的权限查找,比如 755
-user 根据文件拥有者查找
-group 根据文件所属组寻找文件
-size 根据文件小大寻找文件
-o 表达式 或
-a 表达式 与
-not 表达式 非

  1. Shell操作字符串
  1. 字符串截取





  1. 字符串替换
${parameter/pattern/string}

  1. 获取字符串长度


  1. Shell脚本自动安装MySQL
安装mysql脚本:
#!/bin/bash
## auto install mysql
## 假如是第二次装,那么要先停掉服务,并且卸载之前的 mysql
service mysql stop
EXISTS_RPMS=`rpm -qa | grep -i mysql`
echo ${EXISTS_RPMS}
for RPM in ${EXISTS_RPMS}
do
rpm -e --nodeps ${RPM}
done
## 删除残留文件
rm -fr /usr/lib/mysql
rm -fr /usr/include/mysql
rm -f /etc/my.cnf
rm -fr /var/lib/mysql
## 从服务器获取安装 mysql 的 rpm 包
wget http://linux/soft/MySQL-client-5.6.26-1.linux_glibc2.5.x86_64.rpm
wget http://linux/soft/MySQL-server-5.6.26-1.linux_glibc2.5.x86_64.rpm
## 删除之前的密码文件,以免产生干扰
rm -rf /root/.mysql_secret
## 安装服务器
rpm -ivh MySQL-server-5.6.26-1.linux_glibc2.5.x86_64.rpm
## 获取到生成的随机密码
##PSWD=`cat /root/.mysql_secret | awk -F ':' '{print substr($4,2,16)}'`
PSWD=` grep -v '^$' /root/.mysql_secret | awk -F ':' '{print substr($4,2,16)}'`
##PSWD=${PWD:1:16}
## 安装客户端
rpm -ivh MySQL-client-5.6.26-1.linux_glibc2.5.x86_64.rpm
## 然后删除刚刚下下来的 rpm 包
rm -rf MySQL-client-5.6.26-1.linux_glibc2.5.x86_64.rpm
rm -rf MySQL-server-5.6.26-1.linux_glibc2.5.x86_64.rpm
## 提示安装的步骤都完成了。
echo "install mysql server and client is done .!!!!!!"
## 打印出来刚刚生成的 mysql 初始密码
echo "random password is:${PSWD}"
## 开启 mysql 服务
service mysql start
第一次登录修改密码,然后进行权限设置:
[[email protected] bin]# vi initMysql.sh
#!/bin/bash
mysql -uroot -proot << EOF
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT
OPTION;
FLUSH PRIVILEGES;
use mysql;
select host, user, password from user;