能偶尔用上的 awk
英雄总有用武之地。
作者:@nixzhu
对于 app 内的图片,我们可用其名字获取:
|
|
但这样并不安全,我们可能拼错图片的名字,图片本身也可能被删除。而如果我们要在多处使用同一张图片,就更要时时小心。
我们可以用一个 UIImage 的扩展来消除我们的担忧:
|
|
之后我们使用时,只需:
|
|
这样在输入时,除了编辑器会提供自动补全外,编译器也能保证我们不会输入不存在的图片名。
但我们还不能保证图片不会被从我们的 app 工程里删除,所以我们应该加一个测试,保证每次测试运行时,app 所需要的所有图片都能正常访问。
这些都不是问题,问题是,我们可能并没有一开始就考虑这个问题,因此,app 已经累计了很多图片,手动生成这个 extension 实在没有乐趣,自然,轮到脚本登场。(我知道有人会推荐 R.swift,不过它做了太多事,对本地化字符串的生成还不太好,也依赖 CocoaPod,所有并不太喜欢)
我们打开终端,先进入 app 的 Images.xcassets 目录里:ls -l
,输出类似:
|
|
可见,只有imageset
后缀的才是正常的图片,因此我们 grep 过滤一下:ls -l | grep imageset
,输出类似:
|
|
注意上面命令中的|
为管道,它的作用是将其左边命令的输出作为右边命令的输入。
然后就轮到 awk 出场:ls -l | grep imageset | awk '{print $9}'
,将第 9 列切割出来:
|
|
注意 awk 默认使用空白符作为分隔符,$9
表示第 9 列。
我们离得到图片名字列表又近了一步,继续 awk:ls -l | grep imageset | awk '{print $9}' | awk -F"." '{print $1}'
。
这次我们增加了awk -F"." '{print $1}'
,awk 默认用空白符做分割符,但这一句里我们指定用.
做分割符,然后输出第一列:
|
|
这样我们就得到图片名字列表了。接下来我们想把图片名字做一个变换,️以符合 Swift 命名规范,例如将bubble_body
变成bubbleBody
。
因此,继续追加一个 awk 命令:ls -l | grep imageset | awk '{print $9}' | awk -F"." '{print $1}' | awk -F"_" '{out="";for(i=1;i<=NF;i++){if(i==1){out=$i}else{out=out""toupper(substr($i,1,1))substr($i,2)}};print out}'
这次比较复杂,先指定用_
做分割符;然后定义了一个变量out=""
,看起来就是个空字符串;之后进入循环,以i
为变量;其中NF
是 awk 的内置变量,表示当前行的“列数”,这里我们用_
做分割符,因此第一行有两列,NF 就为 2,第二行有三列,N F就等于 3,awk是一行一行地处理输入的,所以每一行的 NF 可以不同;在 for 循环的循环体里(注意大括号),我们先判断 i 是否为 1,是 1 的话就直接赋值给 out,否则就将其第一个字母变为大写再追加到 out 后面,这里的代码比较难看,toupper(substr($i,1,1))
中的 substr 从第 i 列取出第一个字符然后用 toupper 变为大写,接着substr($i,2)
表示剩下的字符串,前面的out=out""...
表示给 out 追加一个空白字符和之后的大写字母和剩下的字符串,这样就实现了首字母大写的功能。
这很麻烦,但我不知道 awk 里是否有更方便的函数,但这里的代码能很工作,于是生成:
|
|
为了之后的代码生成,我们需要没有改变前的名字,因此再修改一下上面的命令:ls -l | grep imageset | awk '{print $9}' | awk -F"." '{print $1}' | awk -F"_" '{out=$0" ";for(i=1;i<=NF;i++){if(i==1){out=$i}else{out=out""toupper(substr($i,1,1))substr($i,2)}};print out}'
只有一点改变,初始化 out 时用了 $0(当前行) 和一个空格,得到:
|
|
最后终于轮到代码生成了,依然再加一段 awk:ls -l | grep imageset | awk '{print $9}' | awk -F"." '{print $1}' | awk -F"_" '{out=$0" ";for(i=1;i<=NF;i++){if(i==1){out=$i}else{out=out""toupper(substr($i,1,1))substr($i,2)}};print out}' | awk '{print "static var xxx_"$2": UIImage {\n\treturn UIImage(named: \""$1"\")!\n}\n"}'
可得到:
|
|
我们的目的就基本达到。毫不夸张地说,我们只用“一句代码”就搞定了。
然后就是搜索项目代码中使用 UIImage 的代码,将它们替换为更安全的用法,并写一个测试,在测试里访问所有的图片,当然,测试代码也可用类似上面的脚本去生成。
我并非 awk 专家,不过我建议所有程序员都学习 grep、awk 以及本文并未提及的 sed 这三个文本处理工具。不用很熟悉,知道它们如何工作即可,用时再查手册。
最终的脚本大概如下:
|
|
===============
欢迎转载,但请一定注明出处! https://github.com/nixzhu/dev-blog
欢迎转发此条
- Tweet https://twitter.com/nixzhu/status/763653023595794432 或
- 微博 http://weibo.com/2076580237/E34xDzoXo
以分享此文或参与讨论!
如果你认为这篇文章对你有所帮助,可用支付宝扫描下方二维码,以捐助慰劳作者的辛苦: