有没有人知道转换方式" 40900000"到" 409-00-000"使用单个命令,sed或awk。 我已经尝试了几种方式与sed但没有运气。我需要批量执行此操作,大约有40k行,其中一些行不正确,因此需要修复它们。
提前致谢
答案 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)
无需运行外部命令,bash
或ksh
可以自行执行。
$ 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的解决方案。