从40900000分割到409-00-000

时间:2014-03-13 12:01:34

标签: bash sed awk

有没有人知道转换方式" 40900000"到" 409-00-000"使用单个命令,sed或awk。 我已经尝试了几种方式与sed但没有运气。我需要批量执行此操作,大约有40k行,其中一些行不正确,因此需要修复它们。

提前致谢

7 个答案:

答案 0 :(得分:5)

使用GNU sed,我会这样做:

sed -r 's/([0-9]{3})([0-9]{2})([0-9]{3})/\1-\2-\3/' filename
# or, equivalently
sed -E 's/([0-9]{3})([0-9]{2})([0-9]{3})/\1-\2-\3/' filename
  • -r-E启用扩展正则表达式模式,这样就无需转义所有括号
  • \1是第一个捕获组(( )
  • 之间的位
  • [0-9]表示范围为0到9
  • {3}表示前面的三个字符或范围

修改:感谢所有评论。

在缺少-r开关或其别名-E的其他系统上,您必须转义上方的( ){ }。这让你:

sed 's/\([0-9]\{3\}\)\([0-9]\{2\}\)\([0-9]\{3\}\)/\1-\2-\3/' filename

以重复为代价,只需重复[0-9]即可避免一些逃脱:

sed 's/\([0-9][0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9][0-9]\)/\1-\2-\3/' filename

为了记录,Perl同样能够做到这一点:

perl -pwe 's/(\d{3})(\d{2})(\d{3})/$1-$2-$3/' filename
  • -p表示打印
  • -w表示启用警告
  • -e表示执行一行
  • \d是"数字"字符类(从零到九)

答案 1 :(得分:2)

您可以使用sed,如下所示:

sed 's/\([0-9][0-9][0-9]\)\([0-9][0-9]\)\([0-9][0-9][0-9]\)/\1-\2-\3/'

或更简洁,使用扩展的正则表达式语法:

sed -E 's/([0-9]{3})([0-9]{2})([0-9]{3})/\1-\2-\3/'

答案 2 :(得分:2)

无需运行外部命令,bashksh可以自行执行。

$ a=12345678
$ [ ${#a} = 8 ] && { b=${a:0:3}-${a:3:2}-${a:5};a=$b;}
$ echo $a
123-45-678
$ a=abc-de-fgh
$ [ ${#a} = 8 ] && { b=${a:0:3}-${a:3:2}-${a:5};a=$b;}
$ echo $a
abc-de-fgh 

答案 3 :(得分:1)

golfing

$ echo "40900000" | awk '$1=$1' FIELDWIDTHS='3 2 3' OFS='-' 
409-00-000

答案 4 :(得分:0)

使用sed:

sed 's/\(...\)\(..\)\(...\)/\1-\2-\3/'

点匹配字符,\(\)的周围区域使其成为一个组。 \1引用第一组。

答案 5 :(得分:0)

只是为了它的乐趣,awk

echo "40900000" | awk '{a=$0+0} length(a)==8 {$0=substr(a,1,3)"-"substr(a,4,2)"-"substr(a,6)}1'
409-00-000

此测试是否有8位数。


更复杂的版本(由于gensub需要gnu awk):

echo "40900000" | awk --re-interval '{print gensub(/([0-9]{3})([0-9]{2})([0-9]{3})/,"\\1-\\2-\\3","g")}'
409-00-000

echo "409-00-000" | awk --re-interval '{print gensub(/([0-9]{3})([0-9]{2})([0-9]{3})/,"\\1-\\2-\\3","g")}'
409-00-000

答案 6 :(得分:0)

STDIN的Turnarround:

echo "40900000" | grep -E "[0-9]{8}" | cut -c "1-3,4-5,6-8" --output-delimiter=-

来自档案:

grep -E "[0-9]{8}" filename | cut -c "1-3,4-5,6-8" --output-delimiter=-

但我完全肯定了Tom Fenech的解决方案。