导读 | 本文为博文 linux —— shell 编程(整体框架与基础笔记)的第4小点的拓展。(本文所有语句的测试均在 Ubuntu 16.04 LTS 上进行) |
目录 |
|
sort :用于排序,常用参数 -t 指定一行的分隔符 -k 指定具体排序的规则 -d 按字典序排列 -f 忽略大小写
-u (unique)丢弃相同指定字段的记录
unique:报告或删除文件中重复的行。 -c 在输出行前加上出现的次数 -d (duplicated)显示重复的行
-u 仅显示不重复的行
wc: 统计文本行数,字数和字符数。 -c 字符数 -w 单词数 -l 行数
pr:将文本转换成适合打印的格式。 -c 显示的列数(截断超出的部分)
fmt: 优化文本的格式。 -w 设置一行显示的最大行宽 -s 只对过长的行进行换行,不要自动回填。
fold:限制文本宽度(强行截断并换行)。 -w 指定宽度 -s 只在空格处换行。
cut :截取行的字段。 -delimiter 设置字段分割符 -f List 设置截取的域
List可以是M,M-,M-N -M;可以用逗号指定多个
join:连接两个文件的数据字段。 join file1 file2 -1 M -2 N M、N指定匹配的字段
tr: 文本替换。 tr set set :将str1上字符替换成str2上对于位置的字符; (可以是 tr 'a-z' 'A-Z')
tr {-d|-s} set :-d 删除set上的每一个字符 ;-s 除去连续出现的set中的字符,至只剩下单个
tr -c (complement 互补)使用set1的外的其他字符 [例子:tr -cs '[:lower:][:upper:]' '[\n*]' 单词表]
0)sed 的作用和工作方式
sed 是一个非交互式的的行编辑器,工作时,从指定的输入读入一行数据存入被称为模式空间(Pattern Space) 的临时缓冲区,然后按照指定的sed编辑命令处理缓冲区里面的内容,将结果输出到标准输出后从模式空间中删除,然后继续读取下一行继续工作。
1) 地址范围
sed -e '1,5d' test.txt
sed -e '/^#/d' test.txt
规则表达式中使用的表达式字符:
字符 | 描述 |
^ | 与行首匹配 |
$ | 与行尾匹配 |
. | 与任意一个字符匹配 |
* | 与之前一个字符的零个或多个出现匹配 |
[] | 与[]之间的所有字符匹配 |
2) 参数
-e 将脚本添加到命令执行,如上面的 '/^#/d'
-n 禁止模式空间的自动打印
替换文本: sed -e "s/benson/BENSON/g" 将benson 替换成大写
sed -e "1,10s/benson/BENSON/g" 将1-10行的benson变成大写
s/// 的 “/”可以被替换:比如 sed -e "s:/usr/local:/usr:g"
多条命令一起执行: sed -n -e "=;p" 打印行号;打印行 (等价与 sed -e "=" -e "p" )
多条命令于同一地址范围:sed -n -e '1,5{s/benson/BENSON/g;s/laur/LAUR/g}'
把命令放在文件fsed里:sed -n -f fsed
awk 具有成为一门语言应有的要素:变量,函数等,是强大的处理工具。
例子:
awk -F ":" '{print "USER:" $1 "\tSHELL: " $7 }' /etc/passwd 结果: USER:root SHELL: /bin/bash USER:daemon SHELL: /usr/sbin/nologin USER:sync SHELL: /bin/sync
上面的命令也可以写入文件file.awk中:
awk -f file.awk /etc/passwd
BEGIN{ FS=":" } {print "USER:" $1 "\tSHELL: " $7 }
1)用户自定义变量
命名规则:[A-Za-z_][A-Za-z0-9_]*
2) 常用的内建变量
变量 | 说明 |
FILENAME | 当前输入的文件名称 |
FNR | 当前输入的文件的记录数 |
FS | 字段分隔符(支持正则表达式),默认空格 |
NF | 当前记录的字段数 |
NR | 在工作(job)中的记录数 |
OFS | 输出字段分隔字符 |
ORS | 输出记录分隔字符(默认为“\n”) |
RS | 输入记录分隔字符 |
3) awk数组 的字符索引支持数字、字符串
sit[google]="https://google.com" sit[baidu]="http;//baidu.com"数组存储是稀疏的,可直接定义如下两项: x[1]=1234 x[1000]=234234delete x 将删除数组里所有的元素删除后,可以继续定义如下: x=567
访问环境变量:ENVIRON["PATH"]
运算符 | 描述 | 例子 |
= += *= /= ^= **= | 赋值 | |
?= | C条件表达式 | |
|| && | 逻辑与或 | |
++-- | 自增自减 | |
~ ~! | 匹配正则表达式和不匹配正则表达式 | |
< <= > >= != == | 关系运算符 | |
空格 | 连接 | |
+ - | 加、减 | |
* / % | 乘除 求余 | |
+ - ! | 一元加减,逻辑非 | |
^ *** | 求幂 | |
$ | 字段引用 | |
in | 数组成员 |
awk支持的算数函数:
sin(x) cos(x) atan2(x,2) :x,y 范围内的余切 int(x):没有舍入地取整 exp(x)求幂 log(x):自然对数 sqrt(x)
rand():产生>=0 <1的随机数 srand(x):x是rand()的种子
条件语句和循环语句与C类似,支持break,continue(可以不使用;结尾)
例子:将下面记录每组一行输出
abc,123 tttt ddddddd,324 ssss ssdd sdfsd sdf dddd sfdfsdf
BEGIN{FS="\n"RS="" # RS设置为""将可以解析多行记录(以空行分隔)ORS="" #输出记录分隔符不要换行 } {x=1while(x<NF){print $x "\t"x++}print $NF "\n" }
结果:
abc,123 tttt dddd ddd,324 ssss ssdd sdfsd sdf dddd sfdfsdf
在函数中,指定的参数将被当做局部变量,而所有函数体内未出现在参数列表中的变量会被视为全局性。为此,awk允许声明过多的参数用于局部使用如:
function add(x,y, sum) { sum = x+y return sum }
如果需要使用函数进行引用传递,只能通过传入数组来实现:
格式化输出:
printf("%s have %d jobs","somebody",3) strout = sprintf("%s have %d jobs","somebody",3)
格式化输出的转义字符:c s d ld (十进制长整数) u lu x lx o lo e(科学计数法表示的浮点数) f g(e或f中比较短的一种)
printf 修饰符: - 左对齐 #显示八进制时在前面加个0;显示十六进制时在前面加0x
+显示defg 转换的整数时,加上正负号 0 填充空白为0
具体的格式为:%-width.precision fotmat-specifier
awk内置字符串函数:
awk函数 | 描述 |
sub(/reg/,newsubstr,str) | 替换第一个匹配的字符串 |
gsub(/reg/,newsubstr,str) | 替换所有匹配 |
index(str,substr) | 返回substr在str中的索引 |
length(str) | 长度 |
match(str,/reg/) | 如果在str中找到正则表达式/reg/匹配的串,则返回出现的位置,未找到则返回0 |
split(str,array,sep) | 使用sep分隔到array |
substr(str,position[,length]) | 返回str从position开始的length个字符 |
tolower(str) | 变小写 |
toupper(str) | 变大写 |
sprintf("fmt",expr) | 格式化返回字符串 |
10001 南京 佛挡杀佛 sdfsdf 10002 天津 发生地方 双方的发生 10003 石家庄 发生地方 发生地方
11000,南京 11003,天津 12000,河北省 13000,品上线 12344,石家庄
BEGIN{FS="[ ,]"OFS="," }NR <= FNR{array[$2]=$1 } NR > FNR{print $1,$2,array[$2] }
awk -f join.awk a.txt b.txt
11000,南京,10001 11003,天津,10002 12000,河北省, 13000,品上线, 12344,石家庄,10003