【问题标题】:Faster way to merge multiple files合并多个文件的更快方法
【发布时间】:2012-11-11 10:53:57
【问题描述】:

我在 Linux 中有多个小文件(大约 70,000 个文件),我想在文件的每一行末尾添加一个单词,然后将它们全部合并到一个文件中。

我正在使用这个脚本:

for fn in *.sms.txt 
do 
    sed 's/$/'$fn'/' $fn >> sms.txt
    rm -f $fn
done

有没有更快的方法来做到这一点?

【问题讨论】:

  • 是的,如果您可以编写一些 Java 或 C++ 代码,您可以并行化这些代码。
  • @MichaelAaronSafyan:你可能是对的,但有一次(大约一年前)我运行了一个复杂的 gsed 过滤器,过滤了几百万个文件(总共 60 GB),将它们从类似 xml 的格式到类似 json 的格式(虽然不完全,但重要的是它比这个问题需要的复杂得多),大约需要 2 个小时才能完成。诚然,它是一台配备 15000 RPM HDD 的 8 核机器,但仍然比我希望的快得离谱。 (注意我说的是gsed,而不是sed。OS X 的sed 慢了两个数量级以上)。
  • 显然,我上面的评论假设您不需要多次运行此查询(即,这就像在将数据提供给数据库进行存储或挖掘之前“清理”数据)。

标签: linux file bash


【解决方案1】:

我尝试使用这些文件:

for ((i=1;i<70000;++i)); do printf -v fn 'file%.5d.sms.txt' $i; echo -e "HAHA\nLOL\nBye" > "$fn"; done

我尝试了您的解决方案,大约需要 4 分钟(真实)来处理。您的解决方案的问题是您在 sed 上分叉了 70000 次!而且分叉比较慢。

#!/bin/bash

filename="sms.txt"

# Create file "$filename" or empty it if it already existed
> "$filename"

# Start editing with ed, the standard text editor
ed -s "$filename" < <(
   # Go into insert mode:
   echo i
   # Loop through files
   for fn in *.sms.txt; do
      # Loop through lines of file "$fn"
      while read l; do
         # Insert line "$l" with "$fn" appended to
         echo "$l$fn"
      done < "$fn"
   done
   # Tell ed to quit insert mode (.), to save (w) and quit (q)
   echo -e ".\nwq"
)

这个解决方案花了大约。 6 秒

不要忘记,ed 是标准的文本编辑器,不要忽视它!如果你喜欢ed,你可能也会喜欢ex

干杯!

【讨论】:

    【解决方案2】:

    与 gniourf_gniourf 的解决方案几乎相同,但没有 ed:

    for i in *.sms.txt 
    do   
       while read line   
       do    
         echo $line $i
       done < $i
    done >sms.txt
    

    【讨论】:

    • 不错的一个! (不过,在这里和那里加上一些引号会更好)。 ed 似乎更快:您的解决方案耗时 7 秒!但是对于 100% bash 解决方案来说是一个很大的 +1。
    【解决方案3】:

    什么,不喜欢awk

    awk '{print $0" "FILENAME}' *.sms.txt >sms.txt
    

    使用gawk,这在我机器上的gniourf_gniourf 的sample 上花费了1-2 秒(根据time)。

    mawk 比这里的gawk 快大约 0.2 秒。

    【讨论】:

      【解决方案4】:

      这个 perl 脚本在每一行的末尾添加实际的文件名。

      #!/usr/bin/perl
      use strict;
      while(<>){
          chomp;
          print $_, $ARGV, "\n";
      }
      

      这样称呼它:

      scriptname *.sms.txt > sms.txt
      

      由于只有一个进程,不涉及正则表达式处理,所以应该很快。

      【讨论】:

        猜你喜欢
        • 2012-02-10
        • 2013-08-11
        • 1970-01-01
        • 2011-11-24
        • 1970-01-01
        • 2016-08-11
        • 2018-02-13
        • 2022-06-10
        • 1970-01-01
        相关资源
        最近更新 更多