《LinuxShell脚本攻略》笔记,Chap-2:命令之乐
简介
各种命令可谓Unix-Like系统中优美的部分,它能帮我们搞定各种繁杂的任务。
一旦你尝试过Linux提供的这些利器,你一定会感到惊讶:以前没有这些命令的时候,自己是什么熬过来的。
最钟爱的莫过于 grep
, awk
, sed
, find
命令了!
本章将会为你介绍一些最有趣同时也是最实用的命令。
用cat进行拼接
#cat命令通常用于读取、显示或拼接文件内容,不过它所具备的能力远不止此
#cat(concatenate, 拼接)
cat file1 file2 ···
echo "Ahaha" | cat - file1 file2 #-指stdin文本文件名
cat -s file3 -- cat file3 | tr -s '\n' #压缩空白行
cat -T test.py #将制表符显示为 ^I, 避免制表符和连续空格误用, 产生错误缩进
cat -n file4 #显示行号
录制与回放终端会话
当你需要准备一个命令行教程时,如果将我们输入命令后的一切按照先后次序记录下来,再进行回放,是不是很nice!
通过 script
, scriptreplay
命令, 把终端会话记录到文件,并回放。
#-t,将时间数据输出到标准错误; -a,追加输出
script -t 2> timing.log -a output.session #两个文件随意取名, 如不将错误重定向会显示在屏幕上导致很乱
输入命令
cmd2
···
exit #退出录制
scriptreplay -t timing.log output.session #播放
文件查找与文件列表
find
是Unix/Linux命令行工具箱中最棒的工具之一。
find
命令沿着文件层次结构向下遍历,匹配符合条件的文件,并执行相应的操作。
#基于文件名及正则表达式搜索
find /home/zhang #列出/home/zhang目录及其子目录线所有文件和文件夹
find /home/zhang -name "*.txt"
find . -name "*.sh" -o -iname "zhang*" #匹配多个
find /home/zhang -path "201710*" #-path将文件路径作为一个整体进行匹配
find . -regex ".*\(\.txt|\.[0-9]+\)$" #匹配以.txt或数字结尾的文件
#使用-maxdepth, -mindepth参数,来限制find的遍历深度
#-type, 根据文件类型搜索。 f(普通文件),d(目录),b(块设备),l(符号链接),s(套接字)等
find /home -maxdepth 1 -type f(d) #参数顺序也会影响find的查找效率
#根据文件类型搜索
find /dev -type b #查看/dev及其子目录下设备文件
find / -maxdepth 1 -type l #查找/下链接文件
#根据文件时间进行搜索
#Unix/Linux文件系统中的每一个文件都有三种时间戳(timestamp),-表示小于,+表示大于
#Unix中并没有所谓的 "创建时间" 的概念
#访问时间(-atime,以天为单位; -amin,以分钟为单位):用户最近一次访问文件时间;
#修改时间(-mtime,以天为单位; -mmin,以分钟为单位):文件最后一次修改时间;
#变化时间(-ctime,以天为单位; -cmin,以分钟为单位):文件元数据(如权限,所有权)最后一次变化时间;
find /home/zhang -type f -mtime 7 #7天前被修改的普通文件
find /home/zhang -type f -amin -10 #搜索10分钟内被修改的普通文件
find . -type f -newer file1.txt #找出比file1.txt新的文件
#基于文件大小的搜索
#b(块,512字节), c(字节), w(字,2字节), k(千字节), M(兆字节), G(吉字节)
find . -type -f -size +100k
#删除匹配的文件
find . -type f -name "*.swp" -delete
#基于文件权限和所有权的匹配
find . -type f -perm 644
find /var/apache -type f -name "*.php" -perm 644 #搜索基于权限的文件
find /var -maxdepth 2 -type f -user zhang #搜索基于用户的文件
#执行命令或动作
#find命令可以借助-exec与其他命令进行结合
#{}是一个特殊字符串,将替换为相应文件名
find . -type f -perm 764 -user zhang -exec chmod 644 {} \; #将所属用户zhang,权限764的文件权限修改为644
find . -type f -mmin +30 -name "*.txt" -exec cp {} {}.old \; #复制最近30内修改的名字为.txt的文件
#-exec结合多个命令
#我们无法在-exec参数中直接使用多个命令,不过我们可以把多个命令写到一个shellscript中,然后执行
-exec ./test.sh {} \;
find . -type f -name "*.sh" -mmin -10 -exec sh {} \;
#让find跳过特定目录
-prune
利用stat
命令查看atime, mtime, ctime :
#stat - display file or file system status
stat 1.txt
#Access:
#Modify:
#Change:
利用touch
命令修改atime, mtime, ctime:
#touch - change file timestamps
#-a change only the access time
#-m change only the modification time
#-d instead of current time
#-t instead of current time
玩转xargs
xargs能够处理stdin并将其转换为特定命令的命令行参数,也可以将单行或多行输入文本转换成其他格式(如多行变单行)。
cmd | xargs
#将多行输入转换为单行输出
echo -e "1\n2\n3" | xargs #将换行符替换为空格
#将单行输入转换成多行输出
echo "1 2 3" | xargs -n 1 #每行一个参数
echo "hahaZhahaZhahaZhaha" | xargs -n 2 -d Z #-d指定分隔符
#读取stdin,将格式化参数传递给命令
cat test.txt | xargs -n 1 ./zhang.sh #zhang.sh arg1; zhang.sh arg2... 每次提供一个参数
cat test.txt | xargs -n X ./zhang.sh #X为参数个数,一次提供全部参数
#指定替换字符串
cat test.txt | xargs -I {} ./zhang.sh {}
#结合find使用xargs
find . -type f -name "*.txt" -print0 | xargs -0 ls #-print0无换行输出, -0将\0作为输入界定符
#统计某文件行数
find /path -type f -name "*.c" -print0 | xargs -0 wc -l
#结合stdin,运用while和子shell
cat file.txt | while read arg; do cat $arg; done == cat file.txt | xargs - {} cat {}
cmd0 | (cmd1; cmd2; cmd3) | cmd4 #子shell
用tr进行转换
#tr - translate or delete characters
#tr命令经常用来编写优美的单行命令
#tr可对来自stdin的字符 进行替换、删除以及压缩
echo "AH WONDERFUL" | tr 'A-Z' 'a-z' #转换大小写
echo "AH WONDERFUL" | tr 'A-Z' 'a-b' --> ab bbbbbbbbb
#tr [option] set1 set2
#如果两个字符集长度不相等,那么set2会不断重复其最后一个字符,直到长度与set1相同
echo 12345 | tr '0-9' '9876543210' #数字加密
echo 87654 | tr '9876543210' '0-9' #数字解密
echo 'He is a cool boy, and she is a beautiful girl' | tr 'A-Za-z' 'NOPQRSRUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm' #加密
echo 'Ur vf n pbby obl, naq fur' | tr 'NOPQRSRUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm' 'A-Za-z' #解密
cat 1.txt | tr '\t' ' ' #将制表符转换为空格
#删除字符
echo "Hello 530 World" | tr -d '0-9' #-d删除,删除数字
Hello World
echo "Hello 520 World" | tr -d -c '0-9' #-c补集
520
#压缩字符,将连续的重复字符压缩为单个字符
echo "GNU's not Unix" | tr -s ' ' #-s压缩,压缩空格
GNU's not Unix
echo -e "1\n2\n3\n4\n5" > sum.txt
cat sum.txt | echo $[ $(tr '\n' '+') 0 ] -- echo $[1+2+3+4+5+0]
#tr字符类
\a 终端鸣响
\b 退格
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
string1-stringN #从字符1到字符N升序过程中的所有字符
[字符*次数]
[:alnum:] #所有字母和数字
[:alpha:] #所有字母
[:digit:] #所有数字
[:lower:] #所有小写字母
[:upper:] #所有大写字母
[:graph:] #所有可打印字符,不含空格
[:print:] #所有可打印字符,包含空格
[:blank:] #所有水平排列的空白字符
[:cntrl:] #所有控制字符
[:punct:] #所有标点字符
[:space:] #所有空白字符
[:xdigit:] #所有十六进制数
[=字符] #指定字符
校验和 与 核实文件完整性
#校验和(checksum)程序从文件中生成校验和密钥,然后利用校验和密钥核实文件的完整性
#校验和对于编写备份脚本或系统维护脚本非常重要,因为它们都会涉及通过网络传输文件
#通过使用校验和核实,我们就可以识别那些在网络传输过程中出现损坏的文件,并重传,从而确保数据完整性
#校验和对于核实数据完整性非常有用
#广泛使用的校验和技术有:md5sum, sha1sum
#对单个文件进行校验
md5sum sum.txt > sum.md5
#302c28003d487124d97c242de94da856 sum.txt
md5sum -c sum.md5 #-c检查
#sum.txt: 确定
#对目录进行校验
#对目录计算校验和意味着我们需要对目录中的所有文件以递归的方式进行计算
yum install -y md5deep
md5deep -r ./dir > dir.md5 #recursive递归
md5sum -c dir.md5
#可以将测试dir下某个文件更改一下,校验的时候会报错
排序、单一、重复
#sort - 对文本文件进行行排序
#uniq - 删除排序文件中的重复行
echo -e "333\n1" > 1.txt; echo -e "22\n22" > 2.txt
sort 1.txt 2.txt -o ./soredt.txt
#1
#22
#22
#333
cat sortec.txt | uniq
#1
#22
#333
sort -n #按数字进行排序
sort -r #逆向排序
sort -M #按月份排序
sort -C #检查是否排序
sort -b #忽略空白
#依据键或列进行排序
sort -k 2 data.txt #依据第二列来排序
#uniq要么使用管道,要么使用排过序的文件作文输入
uniq -u sorted.txt #只显示唯一的行(即没有重复出现的行)
uniq -d sorted.txt #只显示重复的行
uniq -s 2 -w 2 sorted.txt #-s忽略前2个字符,-w指定用于比较的最大字符数
临时文件命名、随机数
#在编写shell脚本时,我们经常需要存储临时文件。最适合存储临时数据的位置是 /tmp
#/tmp目录中的内容会在系统重启后被清空
filename=$RANDOM #RANDOM返回一个随机数
filename2=$$ #当前shell的PID
filename3=$((date +%F)) #通过日期命令
分割文件和数据
#某些情况下,需要把文件分割成多个更小的片段
dd if=/dev/zero bs=100k count=1 of=./data.file #生成一个大小100k内容全是0的文件
split -b 20k data.file #-d指定分割大小
#data.file xaa xab xac xad xae,这五个文件都为20k
#我测试了一下,几个文件加起来数据没变,几个文件总行数没变
#单位有 k, m, G, c(byte), w(word)
#-d以数字为后缀, -a指定后缀长度
split data.file -b 20k -d -a 2 spt #增加前缀名'spt'
#data.file spt00 spt01 spt02 spt03 spt04
split -l 10 data.file #-l按行数来分割文件
#split只能根据大小或行数分割文件
#csplit可以根据文件本身特点进行分割
-f #指定分割后文件前缀
-n #指定分割后文件后缀数字个数
-b #指定后缀格式
根据扩展名切分文件名
#借助%操作符将名称从 “名称.扩展名” 格式中提取出来
file="zhang.txt"
name1=${file%.*} #删除位于%右侧的通配符(.*)所匹配的字符串,通配符从右向左进行匹配
#zhang
#*号通配符,.号
#%属于非贪婪匹配(non-greedy),它会匹配通配符最短结果
#%%属于贪婪匹配(greedy),它会匹配符号条件的最长字符串
name2=${file#*.} #删除位于#右侧的通配符(*.)所匹配的字符串,通配符从左向右进行匹配
#txt
# #属于非贪婪匹配
# ##属于贪婪匹配
#栗子
URL=“www.google.com”
echo ${URL%.*} #非贪婪匹配,移除最右边.及其后面内容
www.google
echo ${URL%%.*} #贪婪匹配
www
echo ${URL#*.} #非贪婪匹配,移除最左边.及其前面内容
google.com
echo ${URL##*.} #贪婪匹配
com
批量重命名和移动
#综合运用find、rename、mv命令
拼写检查与词典操作
#Linux大多数发行版都含有一份词典文件,另外还有一个被称为aspell的拼写检查命令
#words --> /usr/share/dict/linux.words
grep "^good" /usr/share/dict/linux.words
aspell
交互输入自动化
#写一个读取交互式输入脚本
vi jiaohu.sh
#!/bin/bash
read -p "Input a number:" num
read -p "Input name:" name
echo "You have enterd number:$num, name:$name"
echo -e "1\nzhang" | ./jiaohu.sh
You have entered number:1, name:hello
#or
echo -e "1\nzhang" > input.txt
./jiaohu.sh < input.txt
#交互式输入自动化
#用expect实现自动化
yum install -y expect
vim auto_expect.sh
#!/bin/expect
spawn ./jiaohu.sh #spawn指定需要自动化哪一个命令
expect "Input a number:" #expect提供需要等待的消息
send "1\n" #send是要发送的消息
expect "Input name:"
send "zhang"
expect eof #expect eof指明命令交互结束
./auto_expect.sh
网友评论