sort命令 排序
以行为单位对文件内容进行排序,也可以根据不同的数据类型来排序
比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。
sort [选项] 参数 cat file | sort 选项 -n 按照数字进行排序 -r 反向排序 -u 等同于uniq,表示相同的数据仅显示一行 -t 指定字段分隔符,默认使用 [Tab]键分隔 -k 指定排序字段 -o <输出文件>:将排序后的结果转存至指定文件 -f 忽略大小写,会将小写字母都转换为大写字母来进行比较 -b 忽略每行前面的空格
#####按数字排序##### sort -n num.txt #按照数字进行排序 #####UID排序##### sort -t ':' -k 3 -n /etc/passwd #也可以cut 方式 cat /etc/passwd | cut -d ':' -f 1,3 #指定字段分隔符 指定排序第三字段(UID) 按照数字进行排序 #####IP主机位排序##### sort -t '.' -k 4 -n /opt/ip #指定字段分隔符 指定排序第三字段(UID) 按照数字进行排序 #####统计文件夹大小##### du -a | sort -nr -o du.txt #输出文件大小 数字倒序排序 写入du.txt文件
uniq命令 操作重复行
用于报告或者忽略文件中连续的重复行,常与 sort 命令结合使用
unig [选项] 参数 cat file | uniq 选项 cat file | uniq -c #统计出现次数
1.统计IP出现重复过3次的IP地址
cat /opt/ip | sort -n -t '.' -k4 | uniq -c #cat输出文件内容 sort根据.分隔的第四段数字排序 再交给uniq -c统计出现的次数 2 192.168.80.10 1 192.168.80.75 1 192.168.80.100 1 192.168.80.120 2 192.168.80.200 3 192.168.80.245 cat /opt/ip | sort -n -t '.' -k4 | uniq -c | awk '{print $1}' 2 1 1 #awk筛选出次数 1 2 3
将以上命令写入shell脚本,结合for循环输出重复过3次的IP
cat /opt/ip | sort -n -t '.' -k4 | uniq -c > ./count.txt #统计出现次数 ip与次数一同写入文件 IFSB=$IFS #修改for循环分隔符,使用回车,这样遇到ip中的 . 就不会错误分隔 IFS=$'\n' for i in $(cat ./count.txt) do num=$(echo $i | awk '{print $1}' ) #文件中筛选出现次数,赋值给num if [ $num = 3 ];then echo $i | awk '{print $2}' #文件中筛选IP,输出 fi done IFS=$IFSB
改进,不写入文件直接写入count变量(节省IO连接数)
count=`cat /opt/ip | sort -n -t '.' -k4 | uniq -c` #统计出现次数 ip与次数一同写入变量 IFSB=$IFS #修改for循环分隔符,使用回车,这样遇到ip中的 . 就不会错误分隔 IFS=$'\n' for i in $count do num=$(echo $i | awk '{print $1}' ) #文件中筛选出现次数,赋值给num if [ $num = 3 ];then echo $i | awk '{print $2}' #文件中筛选IP,输出 fi done IFS=$IFSB
2.根据/var/log/secure的登录失败记录筛选出正在对本机进行暴力破解的IP,加入hosts.deny文件屏蔽sshd登录
cat /var/log/secure #用户登录日志记录在此
cat /var/log/secure | grep 'Failed password' | awk '{print $13}' | sort -n | uniq -c #cat输出登陆日志文件 grep筛选出FAIL行 awk选取行内第13段(IP) sort与uniq配合统计(失败次数 IP地址) cat /var/log/secure | grep 'Failed password' | awk '{print $13}' | uniq -c #此处sort -n按数字排序可有可无,因为只需要 uniq -c 统计次数并不需要sort排列整齐 12 192.168.80.1
将以上命令写入shell脚本,结合for循环将登录失败重复过3次的IP加入hosts.deny文件屏蔽sshd登录
count=`cat /var/log/secure | grep 'Failed password' | awk '{print $13}' | sort -n | uniq -c` #统计出现次数 ip与次数一同写入变量 IFSB=$IFS #修改for循环分隔符,使用回车,这样遇到ip中的 . 就不会错误分隔 IFS=$'\n' for i in $count do # $( ) 与 ` ` 都为获取其中命令执行结果,作用一样 num=$(echo $i | awk '{print $1}' ) #文件中筛选出现次数,赋值给num if [ $num -gt 3 ];then #出现次数大于3次(登录失败3次以上) IP=`echo $i | awk '{print $2}'` #文件中筛选IP echo "sshd:$IP" >> /etc/hosts.deny #输出到hosts.deny屏蔽sshd方式的登录 fi done IFS=$IFSB
sh pingbi.sh #已经将大于3次登录失败ip屏蔽sshd登录 cat /etc/hosts.deny sshd:192.168.80.1
set -x set +x 调试脚本
例如上方的脚本,可以加上set -x set +x,在其中的命令执行时会输出变量的值,以便调试
set -x 命令块 set +x
count=`cat /var/log/secure | grep 'Failed password' | awk '{print $13}' | sort -n | uniq -c` IFSB=$IFS IFS=$'\n' set -x #✨✨✨ for i in $count do num=$(echo $i | awk '{print $1}' ) if [ $num -gt 3 ];then IP=`echo $i | awk '{print $2}'` echo "sshd:$IP" >> /etc/hosts.deny fi done set +x #✨✨✨ IFS=$IFSB
tr命令 替换字符
tr [选项][参数] #选项 -c 保留字符集1的字符,其他的字符 (包括换行符\n) 用字符集2替换 -d 删除所有属于字符集1的字符 -s 将重复出现的字符串压缩为一个字符;用字符集2 替换 字符集1 -t 字符集2 替换 字符集1,不加选项同结果 #参数 字符集1 指定要转换或删除的原字符集。当执行转换操作时,必须使用参数"字符集2"指定转换的目标字符集。但执行删除操作时,不需要参数"字符集2" 字符集2 指定要转换成的目标字符集。
匹配方式不是精确匹配字符串,而是字符集1位置与字符串2位置一一对应
'ac' 'AX' a对应A c对应X
echo abc | tr 'a-z' 'A-Z' ABC echo abc | tr 'a' 'A' Abc echo abc | tr 'ac' 'AC' AbC echo abc | tr 'ac' 'AX' AbX echo abc | tr -t 'ac' 'AX' #默认就是-t,加不加区别不大 AbX #注意替换方式!
-c 保留字符集1的字符,其他的字符 (包括换行符\n) 用字符集2替换 echo -e "abc\nabcd\nab" abc abcd ab echo -e "abc\nabcd\nab" | tr -c 'ab' '1' ab11ab111ab1 #\n换行符也被替换 echo -e "abc\nabcd\nab" | tr -c 'ab\n' '1' ab1 ab11 ab
-d 删除所有属于字符集1的字符 echo 'hello world' | tr -d ' ' helloworld #删除空字符,让两个字符连在一起 echo 'hello world' | tr -d 'ol' #删除在这个字符串里有ol的所有字符 he wrd
-s 将重复出现的字符串压缩为一个字符;用字符集2 替换 字符集1 echo 'thisssss iiiiiiis tessssssst linnnnnne' | tr -s 'sin' #将重复的字符写入进行压缩 this is test line echo 'thisssss iiiiiiis tessssssst linnnnnne' | tr -s 'sin' 'SIN' thIS IS teSt lINe
使用tr -s命令来将中间空的换行符压缩成一个换行符(或是grep -v)
echo -e "ab\n\n\n\n\n\ncd" | tr -s "\n" ab cd echo -e "ab\n\n\n\n\n\ncd" | grep -v "^$" ab cd echo -e "ab\n\n\ncd" ab cd
使用tr -s命令来将环境变量的:替换为空格方便for循环遍历(无须再修改IFS)
echo $PATH | tr ':' ' ' echo $PATH /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/xue/.local/bin:/home/xue/bin echo $PATH | tr ':' ' ' /usr/local/bin /usr/bin /usr/local/sbin /usr/sbin /home/xue/.local/bin /home/xue/bin
使用tr -s命令将数组变换为列以便sort命令排序
#变为列,才能sort命令排序 echo ${arr1[*]} | tr ' ' '\n' | sort -n 1 2 3 4 5 #变列排序后再变换回去 echo ${arr1[*]} | tr ' ' '\n' | sort -n | tr '\n' ' ' 1 2 3 4 5
#!/bin/bash arr=(24 36 53 12 6 9 1 3) echo "排序前数组的值为; ${arr[@]}" newarr=$(echo ${arr[@]} | tr ' ' '\n' | sort -n | tr '\n' ' ') echo "排序后的数据的值为: ${newarr[@]}"
windows编写的脚本移动到linux中运行需要的转换
cat -v windows.txt cat -A windows.txt
在linux中换行由 $(换行符) 组成
在windows中换行由 ^M(回车) 与 $(换行符) 组成
不做转换直接执行会出错,需要将回车删除。
方法1 tr -d
cat windows.txt | tr -d '\r' > new_windows.txt
方法2 dos2unix
yum install -y dos2unix #yum安装dos2unix dos2unix windows.txt #转换文件格式
cut命令 切片
cut命令—显示行中的指定部分,删除文件中指定字段
cut 参数 cat 文件名 | cut 选项 -b 提取指定段 -f 指定提取的字段 cut命令使用"TAB"作为默认的字段分隔符 -d 指定分隔符 "TAB"是默认的分隔符 --complement 此选项用于排除所指定的字段 --output-delimiter 更改输出内容的分隔符
-b提取指定段
i=abcdefghijklmn echo $i | cut -b 1-3 abc #也可以使用以下两种方法 echo ${i:0:3} expr substr $i 1 3
使用-f和-d来指示分割字段
cat test1 | cut -d '.' -f 4 #等同 cat test1 | awk -F. '{print $4}' cat test1 | cut -d '.' -f 1,4 #1 4段 cat test1 | cut -d '.' -f 2-4 #2到4段
cat test1 192.168.80.100 192.168.80.110 192.168.80.200 cat test1 | cut -d '.' -f 4 100 110 200 cat test1 | awk -F. '{print $4}' 100 110 200 cat test1 | cut -d '.' -f 1,4 192.100 192.110 192.200 cat test1 | cut -d '.' -f 2-4 168.80.100 168.80.110 168.80.200
cut -d -f 输出/etc/passwd过滤用户名与UID
cat /etc/passwd | cut -d ':' -f 1,3 #也可以sort方式 sort -t ':' -k 3 -n /etc/passwd
--complement 反向输出
cat /etc/passwd | cut --complement -d ':' -f 1,3,7 #输出除了1 3 7 段的内容
--output-delimiter 更改输出内容的分隔符
cat /etc/passwd | cut --output-delimiter=' ' -d ':' -f 1,3,7 #根据:分隔取1,3,7段 输出内容分隔符替换为空格 也可以使用awk命令实现相同效果 cat /etc/passwd | awk -F: '{print $1","$3}' #注意分隔符要使用 " " 包含
将大文件拆分为小文件
split 选项 参数 原始文件 拆分后文件名前缀 -l 以行数拆分 -b 以大小拆分 split -l 10 /etc/passwd passwd #10行拆分。
[xue@xue 1]$ split -l 10 /etc/passwd passwd [xue@xue 1]$ ls passwdaa passwdab passwdac passwdad passwdae
将两个文件合并显示
paste 选项 文件1 文件2 -d 替换分隔符 -s 按行显示
vim a vim b 1 a 2 b 3 c 4 d 5 e 6 f
[xue@xue 1]$ paste a b 1 a 2 b 3 c #中间是制表符 4 d 5 e 6 f
paste -d ',' a b 1,a 2,b 3,c #-d 指定分隔符 4,d 5,e 6,f
paste -d ' ' -s a b 1 2 3 4 5 6 a b c d e f
如何合并文件?(面试题)
- cat a.txt b.txt >> c.txt
- vim编辑器 打开a.txt 输入 :r ./b.txt (读取b文件)
- paste a.txt b.txt
有两个文件,每个文件两列,需要合并输出第二列与第四列
vim a a A b B c C d D e E f F g G vim b 1:10 2:20 3:30 4:40 5:50 6:60 7:70
paste -d ' ' a b #连接文件默认分隔符为制表符 改为空格 a A 1:10 b B 2:20 c C 3:30 d D 4:40 e E 5:50 f F 6:60 g G 7:70 paste -d ' ' a b | tr ':' ' ' #paste合并文件,分隔符为空格 #tr将冒号改为空格(b文件是冒号连接的) a A 1 10 b B 2 20 c C 3 30 d D 4 40 e E 5 50 f F 6 60 g G 7 70 paste -d ' ' a b | tr ':' ' ' | cut -d ' ' -f 2,4 #paste合并文件,分隔符为空格 #tr将冒号改为空格(b文件是冒号连接的) #cut根据空格为分隔符 取2 4段 A 10 B 20 C 30 D 40 E 50 F 60 G 70
命令字前加上eval,shell在执行命令前扫描它两次。
eval命令首先会扫描命令行进行所有的替换,然后执行命令。
该命令适用于那些一次扫描无法实现功能的变量。该命令对变量进行两次扫描
echo "hello world" > file1 bianliang="cat file1" echo $bianliang #现在还只是显示变量的值 eval $bianliang #经过eval的扫描后,变量的值被替换为cat file1的执行结果 [xue@xue 1]$ echo $bianliang cat file1 [xue@xue 1]$ eval $bianliang hello world
vim test.sh echo \$$# #输出\$ 脚本后参数个数 eval echo \$$# #输出传参下标为传参长度的值(最后一位) [xue@xue 1]$ sh test.sh 9 8 7 6 5 4 3 $7 3 eval扫描执行顺序为 echo \$$# → echo \$7(参数数量) → 3($7第七位参数的值)
vim test2.sh a=100 b=a echo \$$b eval echo \$$b [xue@xue 1]$ sh test2.sh $a 100 执行顺序为 echo \$$b → echo \$a → 100
vim test3.sh a=100 b=a eval $b=50 echo $a [xue@xue 1]$ sh test3.sh 50 执行顺序为 eval $b=50 → a=b=50 → echo $a → 50