最近做了一个文本
CDR
转换器,从
A
样式转换为
B
样式,如下所示。
A
样式
B
样式
A
样式到
B
样式的转换要点如下:
1.
header
和
trailer
都可直接转换,但是
B
样式需要加上
CDR
的计数
2.
B
样式的
header
还含有
record type
,需要从
A
样式的某个注释行中获取
3.
字段域的转换比较简单,都是一行对一行
4.
A
样式有注释行,转换时要全部删除
转换由
awk
和
sed
完成,完整的命令是这样的:
awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++;
printf("Record (%d)/n", cnt); } else if ( $0 == "." ) {
printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a
| sed '/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type
/(.*/)$//1 "/2"/;s/^F /(.*/) /(.*/)$/
"/1" = "/2"/;/^#/d' > layout b
具体解析如下:
1.
awk 'BEGIN { cnt=0; } {
if ( $0 == "RECORD" ) { cnt++; printf("Record (%d)/n",
cnt); } else if ( $0 == "." ) { printf("End of Record
(%d)/n", cnt); } else { print $0; } }'
layout_a | sed
'/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type /(.*/)$//1
"/2"/;s/^F /(.*/) /(.*/)$/
"/1" = "/2"/;/^#/d' > layout b
判断
CDR
的
header
和
trailer
。如果是
header
,即该行内容为
”RECORD”
,计数器加一,且输出
”Record (?)”
到下一步;如果是
trailer
,即该行内容为
”.”
,输出
”End of Record (?)”
到下一步;否则,不作修改输出到下一步。
2.
awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++;
printf("Record (%d)/n", cnt); } else if ( $0 == "." ) {
printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a
|
sed
'/^Record/{N;N;N;s//n//g;}'
| sed 's/^/(Record (.*)/).*input_type /(.*/)$//1
"/2"/;s/^F /(.*/) /(.*/)$/
"/1" = "/2"/;/^#/d' > layout b
遇到
header
,合并后续三行。因为第四行保留了该
CDR
的
Record type
。
3.
awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++;
printf("Record (%d)/n", cnt); } else if ( $0 == "." ) {
printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a
| sed '/^Record/{N;N;N;s//n//g;}' | sed '
s/^/(Record (.*)/).*input_type
/(.*/)$//1 "/2"/
;
s/^F /(.*/) /(.*/)$/
"/1" = "/2"/;/^#/d' > layout b
从上一步生成的
header
提取合适的内容,形成
B
样式的
header
。注意括号的运用。
4.
awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++;
printf("Record (%d)/n", cnt); } else if ( $0 == "." ) {
printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a
| sed '/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type
/(.*/)$//1 "/2"/;
s/^F /(.*/) /(.*/)$/
"/1" = "/2"/;
/^#/d' > layout b
提取各个字段的键和值,并加上双引号,形成
B
样式的字段域。同样注意括号的运用。
5.
awk 'BEGIN { cnt=0; } { if ( $0 == "RECORD" ) { cnt++;
printf("Record (%d)/n", cnt); } else if ( $0 == "." ) {
printf("End of Record (%d)/n", cnt); } else { print $0; } }' layout_a
| sed '/^Record/{N;N;N;s//n//g;}' | sed 's/^/(Record (.*)/).*input_type
/(.*/)$//1 "/2"/;s/^F /(.*/) /(.*/)$/
"/1" = "/2"/;
/^#/d
' > layout b
删除剩余的注释行。