专栏首页数据之美那些 Shell、Awk 中自动隐式类型转换的“坑”

那些 Shell、Awk 中自动隐式类型转换的“坑”

1、问题:

在林林总总的编程语言里,弱类型的语言着实不少,一方面这种“动态类型”用起来很方便,而另一方面则“坑”你没商量~ 常见的 SQL、Shell、Awk 都会遇到各种暗藏的“隐式类型转换”,稍不留神就会“掉坑”。下面就列举一些 shell、awk 里的自动隐式类型转换 case,防止掉坑。

  • 注意 shell、awk 的变量为空 字符串、变量为空 未定义初始值的隐式转换问题:
# shell 下的字典排序比较
root@localhost 10:59:23 /opt/script >
[[ (( a > 0 )) ]] && echo 1  							
1									
root@localhost 10:59:34 /opt/script >
[[ (( 00 > 0 )) ]] && echo 1  
1
# 双括号不做算术比较,而是字符串的字典比较,等同于 [[]]
[[ (( 0 == 0 )) ]] && echo 1   							
1						
root@localhost 13:04:27 /opt/script >
[[ (( 11 > 110 )) ]] && echo 1   
root@localhost 13:04:34 /opt/script >
# shell 的字符串比较不做转换,严格按照字面量字典比较
root@localhost 11:51:41 /opt/script >
[[ a == "" ]] && echo 1		
root@localhost 14:00:53 /opt/script >
[[ a > "" ]] && echo 1 
1
root@localhost 14:00:59 /opt/script >
[[ a > 0 ]] && echo 1  
1
# shell 的数字类型隐式转换:变量未定义会被转换为 0
root@localhost 11:53:56 /opt/script >
[[ a -eq 0 ]] && echo 1    
1														
root@localhost 11:54:11 /opt/script >
[[ a1 -eq 1 ]] && echo 1 								
root@localhost 11:55:11 /opt/script >
[[ 1a -eq 1 ]] && echo 1 
-bash: [[: 1a: value too great for base (error token is "1a")
# awk 隐式类型只转换 1a,不转换 a1
root@localhost 11:55:15 /opt/script >
echo|awk '{print 1a == 1 }'			
1
# awk 外置变量未定义会被置为空字符串,且空字符串不会隐式转换为数字
root@localhost 14:12:57 /opt/script >
echo|awk -va= '{print a == 0 }' 
0				
root@localhost 14:18:08 /opt/script >
echo|awk '{print "" == 0 }' 
0
root@localhost 14:13:01 /opt/script >
echo|awk -va= '{print a == "" }'
1
# awk 内置变量未定义默认会隐式转换为数字 0 或者空字符串
root@localhost 14:13:12 /opt/script >
echo|awk '{print a == 0 }'      
1
root@localhost 14:13:48 /opt/script >
echo|awk '{print a == "" }'
1
# awk 内置变量在比较时,一方加了双引号,则最终结果当做字符串比较(未定义的变量还是会自动隐式转换)
root@localhost 14:23:43 /opt/script >
echo|awk '{print 0b == "00" }' 	
0		
root@localhost 14:23:47 /opt/script >
echo|awk '{print 0b == 00 }'   
1
root@localhost 14:36:57 /opt/script >
echo|awk '{print "00" == 0 }' 	# 明确标识字符串的不再隐式转换为数字
0
# awk 中的隐式转换:无论最终结果是否以数字比较,未定义的变量都会自动隐式转换
root@localhost 14:27:49 /opt/script >
echo|awk '{print 0b == "0" }' 	
1			
echo|awk '{y=0b; print y == "0" }'     
1
echo|awk '{print 0b == 0 }'  
1
echo|awk '{y="0b"; print y == "0" }' 
0
echo|awk '{y="0b"; print +y == "0" }' 
1
Jun@VAIO 23:49:55 ~ >
echo|awk '{y="0b"; print +y == "00" }'
0
Jun@VAIO 23:49:59 ~ >
echo|awk '{y="0b"; print (+y > "00") }'
0
Jun@VAIO 23:50:14 ~ >
echo|awk '{y="0b"; print +y < "00" }'
1
root@localhost 14:41:16 /opt/script >
echo|awk '{print "00"a == "00" }' 
1
# awk 的外置变量参与比较时,与内置变量的隐式转换特性不同,如果数字中含有非数字字符串则直接被当做字符串。
# 也就是说 awk 外置变量不具有内置变量对 非数字字符隐式转换 的特性
root@localhost 16:16:27 /opt/script >
a=0b; echo|awk -vm="$a" '{print m; print m == 0; print int(m) == 0 }'	
0b
0
1
root@localhost 16:16:39 /opt/script >
a=00; echo|awk -vm="$a" '{print m; print m == 0; print int(m) == 0 }'  
00
1
1
root@localhost 16:16:59 /opt/script >
a=00; echo|awk -vm="$a" '{print m; print m == "0"; print int(m) == "0" }'
00
0
1
root@localhost 16:20:11 /opt/script >
a=00; echo|awk -vm="$a" '{print m; print m == "00"; print int(m) == 0 }'  
00
1
1
Jun@VAIO 00:33:24 ~ >
a=0b; echo|awk -vm="$a" '{b=0;print 0b; print 0b == 0; print int(m) == 0 }'
00
0
1
# 为避免上述 case 的各种歧义和不确定性,还是老老实实的用 +、int 强制转换吧~
Jun@VAIO 00:43:55 ~ >
echo|awk '{print int("1/*")}'
1
Jun@VAIO 00:47:31 ~ >
echo|awk '{print int("*/1")}'
0
Jun@VAIO 00:47:38 ~ >
echo|awk '{print +"*/1"}'
0
Jun@VAIO 00:47:47 ~ >
echo|awk '{print +"1/*"}'
1
Jun@VAIO 00:47:53 ~ >

2、结论:

(1)shell 的自动隐式类型转换相当弱,而 awk 相对而言容错性好 (2)从 case 来看,如果单纯的靠 shell、awk 的自动隐式类型转换相当不靠谱,极其容易出错, (3)为获得确定的结果,还是老老实实的强制转换吧,比如 awk 中使用 +、int 等。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • shell 学习笔记(17)

    声明:转载需署名出处,严禁用于商业用途! 1601.关于rsync相同文件后 du 大小不一样的问题: 不一样大小很正常,因为文件系统的block...

    用户1177713
  • shell 学习笔记(19)

    声明:转载需署名出处,严禁用于商业用途! 1801.关于 nohup 后台运行的问题: nohup就是拒绝hup信号,没什么其他用途, 如...

    用户1177713
  • shell 学习笔记(16)

    转载请注明出处: https://cloud.tencent.com/developer/user/1177713/activities 注:以前的1-15连载...

    用户1177713
  • Linux对文件中的特殊字符进行替换(添加对NUL的处理)

    https://stackoverflow.com/questions/5800035/how-to-replace-nul-in-vi

    小徐
  • awk工具

    叶瑾
  • 只用一行来颠覆你处理文件的方式

    引言:生物信息学文件多样,通常我们会遇到各种将不同格式进行转换或者把文件修改成我们想要的那种格式的需求,不懂生信的小伙伴们会请教会生信的小伙伴,其实会生信的同学...

    阿凡亮
  • node-package.json 文件package-lock.json

    eadela
  • 【NLP】初次BERT使用者的可视化指南

    用可视化的方式演示了如何用Bert来做一个句子分类的应用,每一步都有非常详细的图解,特别的清楚。

    yuquanle
  • 【连载】两百行Rust代码解析绿色线程原理(四)一个绿色线程的实现

    在我们开始之前,我得提醒你我们编写的代码非常不安全,并且这也不是编写 Rust 代码的 “最佳实践”。我希望在不引入很多不必要的复杂性的前提下使其尽可能安全,所...

    MikeLoveRust
  • Newbe.Mahua 2.2 可用性修复

    虽说该版本是一个次要更新版本,但实际上现在版本在这两个平台上已经完全失效,必须升级为最新版本。

    newbe36524

扫码关注云+社区

领取腾讯云代金券