bash - shell脚本中的性能问题

标签 bash shell unix

我有一个 200 MB 的制表符分隔文本文件,其中包含数百万行。在此文件中,我有一列包含多个位置,例如 US 、 UK 、 AU 等。

现在我想根据这个专栏来破解这个文件。虽然这段代码对我来说运行良好,但面临性能问题,因为根据位置将文件拆分为多个文件需要 1 个多小时。这是代码:

#!/bin/bash

read -p "Please enter the file to split " file
read -p "Enter the Col No. to split " col_no

#set -x

header=`head -1 $file`

cnt=1
while IFS= read -r line
do
        if [ $((cnt++)) -eq 1 ]
        then
                echo "$line" >> /dev/null
        else
                loc=`echo "$line" | cut -f "$col_no"`
                f_name=`echo "file_"$loc".txt"`
                if [ -f "$f_name" ]
                then
                        echo "$line" >> "$f_name";
                else
                        touch "$f_name";
                        echo "file $f_name created.."
                        echo "$line" >> "$f_name";
                        sed -i '1i '"$header"'' "$f_name"
                fi
        fi

done < $file

这里应用的逻辑是,我们只读取整个文件一次,并且根据位置,我们创建数据并将其附加到其中。

请对代码提出必要的改进建议,以提高其性能。

以下是示例数据,并用冒号而不是制表符分隔。国家/地区代码位于第 4 列:

ID1:ID2:ID3:ID4:ID5
100:abcd:TEST1:ZA:CCD
200:abcd:TEST2:US:CCD
300:abcd:TEST3:AR:CCD
400:abcd:TEST4:BE:CCD
500:abcd:TEST5:CA:CCD
600:abcd:TEST6:DK:CCD
312:abcd:TEST65:ZA:CCD
1300:abcd:TEST4153:CA:CCD

最佳答案

有几点需要牢记:

  1. 使用 while read 读取文件速度很慢
  2. 创建子 shell 和执行外部进程很慢

这是文本处理工具的工作,例如 awk。

我建议你使用这样的东西:

# save first line
NR == 1 {
    header = $0
    next
}

{
    filename = "file_" $col  ".txt"

    # if country code has changed
    if (filename != prev) {
        # close the previous file
        close(prev)
        # if we haven't seen this file yet
        if (!(filename in seen)) {
            print header > filename
        }
        seen[filename]
    }

    # print whole line to file
    print >> filename
    prev = filename
}

使用以下内容运行脚本:

awk -v col="$col_no" -f script.awk file

其中 $col_no 是一个 shell 变量,其中包含带有国家/地区代码的列号。

如果您没有太多不同的国家/地区代码,则可以将所有文件保持打开状态,在这种情况下,您可以删除对 close(filename) 的调用。

您可以在问题中提供的示例上测试脚本,如下所示:

awk -F: -v col=4 -f script.awk file

请注意,我添加了 -F: 将输入字段分隔符更改为 :

关于bash - shell脚本中的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41238656/

相关文章:

bash - bash 中的 OR 逻辑运算符

linux - 命令列出除 . (点)和..(点点)

c - 如何解析系统日志时间戳

php - 使用 shell_exec 或 exec 作为不同的 unix 用户?

bash - 如何使用 bash 从文本文件中提取列

linux - 如何在 bash 中打印具有特定列匹配数组成员的行

bash - 如何在变量中使用变量?

linux - 用于从另一个文件的 block 组成文件的 shell 命令

linux - 为什么我必须输入 "\\\0"才能在zsh中创建一个字符串 "\0"?

sorting - 使用一行的前六个字符在unix中对文件进行排序