awk处理9G级别文件
如何处理9G级别文件,直接导入性价比不高,那就按照流处理器进行
awk处理单文件级别
awk轻松解决大文件级别的遍历问题,并提取需要的字段。
awk -F"," '/_028\./{print $1,",",$3,",",$4;}' js_df_20220309.csv > 20220309_28.csv
## /_028\./ 的28表示第28台风电机组,$1,$3,$4 分别为时间、物理量、值
## /_029\./ 的29表示第29台风电机组,$1,$3,$4 分别为时间、物理量、值
那如何提取所有机组信息,每个机组都变换一下 那如何解决一个文件夹内的所有文件问题? 每个文件名字都包含年月日信息,另外awk的模式不能包含变量,那么只能说awk解析的时候,我们必须把字面值提供给awk了
第一步:尝试解析2级循环,循环91台机组
seq等宽输出
seq等宽输出可以采用-w option,这样输出就是相同长度,可以提供模式匹配需要
seq -w 001 091
我的测试代码:
for day in `ls *.csv`;do day1=${day:6};realDay=${day1:0:-4};echo $realDay; for turbine in `seq -w 003 1 91`; do turbinePattern="_$turbine\."; outputFilename=$realDay"_"$turbine".csv";echo $turbinePattern,$turbine,$outputFilename;done;done
错误的命令
下面命令无法获得你想要单台机组信息,因为$turbinePattern根本就不会解析为`_028.`的 模式,因为//不能解析变量,所以解决办法是我们提供斜杠号之间变量值
但是perl的模式匹配中确实可以,参考perl拆分大文件 可见perl正则的强大。
单行执行程序:
for day in `ls *.csv`;do day1=${day:6};realDay=${day1:0:-4};echo $realDay; for turbine in `seq -w 003 1 91`; do turbinePattern="_$turbine\."; outputFilename=$realDay"_"$turbine".csv";awk -F"," '/$turbinePattern/{print}' echo $turbinePattern,$turbine,$outputFilename;done;done
bash包装awk可执行语句
我们可以包装awk命令,最后交给bash执行(很重要的bash命令)
我的awk命令封装测试代码(重大突破)
注意双引号要用反斜杠去引用!(去引用是一个基本的业务操作)
86151@DESKTOP-O9MPS4C /cygdrive/f/js_df/ceshi
$ echo "awk -F\",\" '{print $2}' 20200109_28.csv >heklo.csv"|bash
86151@DESKTOP-O9MPS4C /cygdrive/f/js_df
$ d1="_001\.";cmd="awk -F\",\" '/$d1/{print \$1,\",\",\$3,\",\",\$4;}' js_df_20220109.csv > 20220009_001.csv" ;echo $cmd|bash
最终的成品
- 遍历文件
- 文件名字截取重要部分
- 生成所有机组的匹配模式
- 生成awk命令字符串,包装机组模式变量
- bash执行
for day in `ls *.csv`;do day1=${day:6};realDay=${day1:0:-4};echo $realDay; for turbine in `seq -w 001 091`; do turbinePattern="_$turbine\."; outputFilename=output/$realDay"_"$turbine".csv";cmd="awk -F\",\" '/$turbinePattern/{print \$1,\",\",\$3,\",\",\$4;}' $day >$outputFilename";echo $cmd|bash;done;done
sed存在的意义
awk于1977年出生,现在46岁了,sed比awk大2-3岁。
-
快速读取前面几行
-
最后一行或者中间行快速插入相关信息
-
最流行的替换功能`sed ’s/hell//’ file`, 如果加入"-i"选项则表示直接在文件中修改;
还可以指定行进行修改,比如"sed ‘3,6s/my/yours/g’ file"
每行匹配可能有多个,还可以指定每行第几个匹配进行修改,比如第二个匹配修改"sed ‘3,6s/my/yours/2’ file" 比如第三个匹配修改"sed ‘3,6s/my/yours/3’ file"
还比如第三个以后的所有匹配都修改,加入g即可,“sed ‘3,6s/my/yours/3g’ file”
还比如匹配位置后面连续3行, “$ sed ‘dog,+3s/^/# /g’ pets.txt” +3代表匹配后的连续3行
命令还可以打包 # 对3行到第6行,匹配_This_成功后,再匹配_fish_,成功后执行d命令 $ sed ‘3,6 {/This/{/fish/d}}’ pets.txt
参考cool sed
sed ’s/my/[&]/g’ my.txt ,&代表匹配的my
sed ‘N;s/\n/,/’ pets.txt N命令快速合并前后两行(1,2行合并为1行,3,4行合并为1行)
可以学习一下陈浩的酷壳博客 sed很关键的几个概念是地址(行或者模式指定),!是否执行,cmd命令流(增删查找)
10q,代表读到第十行则quit!
$ sed '10q' js_df_20220109.csv
2022-01-09 00:00:01,1641657601032,JS_DF_1_008.1.DD,0.0,,tenant_system,,1641657600,1
2022-01-09 00:00:01,1641657601032,JS_DF_1_008.1.DE,34.7,,tenant_system,,1641657600,1
- 最后一行或者中间行快速插入相关信息
[root@www ~]# sed -i '$a # This is a test' regular_express.txt
[root@www ~]# cat regular_express.txt
runoob!
google!
taobao!
facebook!
zhihu-
weibo-
# This is a test
由於 $ 代表的是最后一行,而 a 的动作是新增,因此该文件最后新增 # This is a test!
sed 的 -i 选项可以直接修改文件内容,这功能非常有帮助!举例来说,如果你有一个 100 万行的文件,你要在第 100 行加某些文字,此时使用 vim 可能会疯掉!因为文件太大了!那怎办?就利用 sed 啊!透过 sed 直接修改/取代的功能,你甚至不需要使用 vim 去修订
awk获取机组台数信息
awk字符串分割(多个分割模式) uniq去重(uniq -c 加上统计功能)
awk -F"," '{split($3,a,"[_.]");print a[4];}' /tmp/test.csv|uniq
当然也可以使用 substr
awk -F ',' '{print substr($3,6)}' # ---> 表示是从第3个字段里的第6个字符开始,一直到设定的分隔符","结束.
substr($3,10,8) #---> 表示是从第3个字段里的第10个字符开始,截取8个字符结束.
substr($3,6) #---> 表示是从第3个字段里的第6个字符开始,一直到结尾