Shell中高效分割字符串

2017-01-12 09:59:41来源:作者:碎片人点击

通常来说,使用 shell 脚本时候不需要太顾及程序的效率性,能完成任务,只要不是太慢,都可以接受。

但在一些特定应用场合,脚本效率也是一个硬性限制,不能耗时太久,比如说,用 shell 来编写一些处理 HTTP 请求的 CGI 程序,脚本的执行效率直接影响了 HTTP 的响应速度。

在 shell 中分割字符串有多种方法,比如利用 awk、cut 工具,还有内置方法,虽然效果相同,但是执行效率差距较大,尤其在处理大数据量上更是显著。

用 cut 工具分割字符串一般是以下用法:

# -f 指定列序号 -d 指定分隔符echo $line | cut -f1 -d ' '

用 awk 工具分割字符串类似:

# $1 代表第一列 以此类推# -F 指定分割符号echo $line | awk -F ' ' {'print $1'}

内部方法分割字符串,用的是 IFS变量和 set命令:

# 设置分隔符IFS=" "# 分割 lineset -- $line# $1 代表第一列,以此类推echo $1

在 shell 脚本中,使用 awk/cut 这些工具在运行时会创建 sub-shell 来运行,相当于 C 语言中的 system/ popen调用,当需要使用的次数比较多时,这种调用会显著降低脚本的执行速度(创建进程是比较昂贵的)。

而使用内置方法则无需调用外部工具,执行起来效率更高,没有额外开销。

以处理 1000 行的空格分割的数字并分别累加为例,其文件内容大概如下:

1 25 30 1002 26 33 1023 27 36 104...999 1023 3024 20961000 1024 3027 2098

保存为文件 test.data。然后编写2个测试脚本, split1.sh和 split2.sh。

split1.sh内容如下:

#!/bin/shDataFile="test.data"if [ ! -e $DataFile ]; thenecho "Fail to open file"exit 1fiF1=0F2=0F3=0F4=0# 设置分割符IFS=" "while read linedo[ -z "$line" ] && continueset -- $lineF1=$((F1+$1))F2=$((F2+$2))F3=$((F3+$3))F4=$((F4+$4))done < $DataFileecho "F1=$F1"echo "F2=$F2"echo "F3=$F3"echo "F4=$F4"

split2.sh文件内容如下:

#!/bin/shDataFile="test.data"if [ ! -e $DataFile ]; thenecho "Fail to open file"exit 1fiF1=0F2=0F3=0F4=0IFS=" "while read linedo[ -z "$line" ] && continuel1=$(echo $line | cut -f1 -d ' ')l2=$(echo $line | cut -f2 -d ' ')l3=$(echo $line | cut -f3 -d ' ')l4=$(echo $line | cut -f4 -d ' ')F1=$((F1+$l1))F2=$((F2+$l2))F3=$((F3+$l3))F4=$((F4+$l4))done < $DataFileecho "F1=$F1"echo "F2=$F2"echo "F3=$F3"echo "F4=$F4"

split1.sh使用内置方法, split2.sh使用 cut 工具来处理。在 shell 中运行程序并用 time命令监控执行时间,会发现速度对比特别显著。

以本人测试电脑为例,内置方法执行输出如下:

$ time ./split1.shF1=500500F2=524500F3=1528500F4=1099000real0m0.045suser0m0.024ssys0m0.020s$ time ./split2.shF1=500500F2=524500F3=1528500F4=1099000real0m4.603suser0m0.004ssys0m0.736s

粗略看出执行速度相差 100 倍左右。

备注:因为要获取各列数据累加,所以在脚本2中,使用了4次 cut 调用,相当于字符串分割了4此,而脚本1中只使用了一次字符串分割,这种策略也显著增加了执行开销。可以通过使用数组返回 cut 结果来避免多次调用,但是这得看 shell 环境是否支持,某些情况下是不支持数组的,比如 busybox 的 sh环境。

(完)

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台