unix中的Overpunch字符转换

时间:2014-09-15 17:18:26

标签: unix

考虑下面管道分隔文件中的第3列。

A001|akdfjhafa|0000000000034a|hello 
B001|bdfaakf|00000008754l|world 
B002|sdbvhjsdhg|00000829838{|consider 
C003|sdjfhjsdd|00000043724}|bracket 

我需要在超量字符转换后将字段转换为十进制值

输出应该是

A001|akdfjhafa|3.41|hello 
B001|bdfaakf|-875.43|world 
B002|sdbvhjsdhg|82983.80|consider 
C003|sdjfhjsdd|-4372.40|bracket 

公式很简单

a=1 
b=2 
c=3 
... 
h=8 
i=9 
j=-1 
k=-2 
... 
q=-8 
r=-9 
{=0 
}=-0 

示例:

00000043724} = -4372.40 
1234k = -123.42 
1234p = -123.47 
1234e = 123.45 

我的想法如下

# replace {,a through 1 using below command. 
awk -F"|" '
  BEGIN {OFS="|"}
  { gsub("a", "1", $3);
    gsub("b", "2", $3);
    gsub("c", "3", $3);
    gsub("d", "4", $3);
    gsub("e", "5", $3);
    gsub("f", "6", $3);
    gsub("g", "7", $3);
    gsub("h", "8", $3);
    gsub("i", "9", $3);
    gsub("{", "0", $3);
    print $0
  }' test.dat 

但是当j,k,l,m,n,o,p,q,r,}出现时,我用相应的数值替换并打印$ 1,$ 2," - " $ 3,$ 4 。

之后,删除所有前导零。

2 个答案:

答案 0 :(得分:2)

这可以在本机bash(不是/ bin / sh,但是bash)中实现,如下所示:

#!/bin/bash
while IFS='|' read -r -a items; do
   text=${items[2]}
   [[ $text =~ [^1-9][0-9]+$ ]] && text=${BASH_REMATCH[0]} # strip leading 0s
   text=${text//a/1} text=${text//b/2} text=${text//c/3}
   text=${text//d/4} text=${text//e/5} text=${text//f/6}
   text=${text//g/7} text=${text//h/8} text=${text//i/9}
   text=${text//j/-1} text=${text//k/-2} text=${text//l/-3}
   text=${text//m/-4} text=${text//n/-5} text=${text//o/-6}
   text=${text//p/-7} text=${text//q/-8} text=${text//r/-9}
   text=${text//"{"/0} text=${text//"}"/-0}
   items[2]=$text                                   # write back to array
   printf -v output '%s|' "${items[@]}" # put all items in string with pipes after them
   printf '%s\n' "${output%'|'}"        # strip last pipe, print line with trailing newline
done <test.dat

答案 1 :(得分:0)

我设法编写了一组暂时帮助我的代码。

以下代码将替换&#34; a&#34;通过&#34;我&#34;和&#34; {&#34;具有相应的正值。 gsub(/ ^ 0 * /,&#34;&#34;,$ 3) - 删除前导零。 sed&#39 / s /.. $ /。&amp; /; t; s /^. $ /。0&amp; /&#39; - 在行中最后2个字符前添加小数。

awk -F"|" 'BEGIN {OFS="|"}{gsub("a","1",$3);gsub("b","2",$3);gsub("c","3",$3);gsub("d","4",$3);gsub("e","5",$3);gsub("f","6",$3);gsub("g","7",$3);gsub("h","8",$3);gsub("i","9",$3);gsub(/^0*/,"",$3);print $1,$2,$4,$3}' test.dat| sed 's/..$/.&/;t;s/^.$/.0&/'|sed 's/[{]/0/g' > test1.dat

rm test

以下代码将取代&#34; j&#34;通过&#34; r&#34;和&#34;}&#34;具有相应的负值,并包含一个特殊字符(〜),稍后将用于过滤数据并添加&#39; - &#39;。

awk -F"|" 'BEGIN {OFS="|"}{gsub("j","~1",$4);gsub("k","~2",$4);gsub("l","~3",$4);gsub("m","~4",$4);gsub("n","~5",$4);gsub("o","~6",$4);gsub("p","~7",$4);gsub("q","~8",$4);gsub("r","~9",$4); print}' test1.dat |sed 's/[}]/~0/g'>test2.dat

rm test1

grep -v "~" test2.dat > test3.dat

grep "~" test2.dat|sed 's/~//g'|awk -F"|" '{OFS="|";print $1,$2,$3,"-"$4}' >> test3.dat

rm test2

awk -F"|" '{OFS="|";print $1,$2,$4,$3}' test3.dat >test.dat

rm test3