在此答案中(如何使用sed删除文件的第一行?),有两种删除文件中第一条记录的方法:
sed '1d' $file >> headerless.txt** - - - - - - - - 要么 - - - - - - - - **
tail -n +2 $file >> headerless.txt就我个人而言,我认为该tail选项在外观上更令人愉悦且更具可读性,但可能是因为我受到了挑战。
哪种方法最快?
tail缺乏跨平台兼容性的内容。
                在此答案中(如何使用sed删除文件的第一行?),有两种删除文件中第一条记录的方法:
sed '1d' $file >> headerless.txt** - - - - - - - - 要么 - - - - - - - - **
tail -n +2 $file >> headerless.txt就我个人而言,我认为该tail选项在外观上更令人愉悦且更具可读性,但可能是因为我受到了挑战。
哪种方法最快?
tail缺乏跨平台兼容性的内容。
                Answers:
sedvs. tail删除文件第一行的性能sed 是非常强大且功能强大的工具,但这就是它使速度变慢的原因,特别是对于具有多行的大型文件而言。
tail 只会做一件简单的事情,但是那件事情却又好又快,即使对于有很多行的较大文件也是如此。
对于中小型的文件,sed并tail正在执行同样快(或慢,取决于你的期望)。但是,对于较大的输入文件(多个MB),性能差异会显着增长(对于数百MB范围内的文件,其数量级是明显的),其性能tail明显优于sed。
我们要分析的命令是:
sed '1d' testfile > /dev/null
tail -n +2 testfile > /dev/null请注意,我/dev/null每次都要对输出进行管道传输,以消除终端输出或文件写入作为性能瓶颈。
让我们设置一个RAM磁盘,以消除可能造成瓶颈的磁盘I / O。我个人tmpfs在/tmp所以我只是把我放在testfile那儿进行这个实验。
然后,我一次$numoflines使用此命令创建一个随机测试文件,该文件包含指定数量的具有随机行长和随机数据的行(请注意,这绝对不是最佳选择,对于> 2M的行来说它确实变慢了,但是谁在乎,不是我们正在分析的东西):
cat /dev/urandom | base64 -w0 | tr 'n' '\n'| head -n "$numoflines" > testfile哦,顺便说一句。我的测试笔记本电脑在Intel i5-6200U CPU上运行64位Ubuntu 16.04。只是为了比较。
testfile:运行上面的命令会numoflines=10000000生成一个随机文件,其中包含10M行,占用了600 MB以上的空间-它非常大,但是让我们开始吧,因为我们可以:
$ wc -l testfile 
10000000 testfile
$ du -h testfile 
611M    testfile
$ head -n 3 testfile 
qOWrzWppWJxx0e59o2uuvkrfjQbzos8Z0RWcCQPMGFPueRKqoy1mpgjHcSgtsRXLrZ8S4CU8w6O6pxkKa3JbJD7QNyiHb4o95TSKkdTBYs8uUOCRKPu6BbvG
NklpTCRzUgZK
O/lcQwmJXl1CGr5vQAbpM7TRNkx6XusYrOtestfile:现在,让我们先对这两个命令进行一次定时运行,以估算我们正在工作的幅度。
$ time sed '1d' testfile > /dev/null
real    0m2.104s
user    0m1.944s
sys     0m0.156s
$ time tail -n +2 testfile > /dev/null
real    0m0.181s
user    0m0.044s
sys     0m0.132s对于大文件,我们已经看到了一个非常清晰的结果,tail比快一个数量级sed。但是,只是为了好玩,并确保没有随机的副作用有很大的不同,让我们做100次:
$ time for i in {1..100}; do sed '1d' testfile > /dev/null; done
real    3m36.756s
user    3m19.756s
sys     0m15.792s
$ time for i in {1..100}; do tail -n +2 testfile > /dev/null; done
real    0m14.573s
user    0m1.876s
sys     0m12.420s结论保持不变,sed无法删除大文件的第一行,tail应在此处使用。
是的,我知道Bash的循环构造很慢,但是我们在这里只进行了相对较少的迭代,与sed/ 相比,普通循环花费的时间并不重要。tail运行时。
testfile:现在为完整起见,让我们看一下在kB范围内有一个小的输入文件的更常见情况。让我们使用创建一个随机输入文件numoflines=100,如下所示:
$ wc -l testfile 
100 testfile
$ du -h testfile 
8,0K    testfile
$ head -n 3 testfile 
tYMWxhi7GqV0DjWd
pemd0y3NgfBK4G4ho/
aItY/8crld2tZvsU5lytestfile:正如我们可以预期的那样,此类小文件的计时时间根据经验可能在几毫秒的范围内,让我们立即进行1000次迭代:
$ time for i in {1..1000}; do sed '1d' testfile > /dev/null; done
real    0m7.811s
user    0m0.412s
sys     0m7.020s
$ time for i in {1..1000}; do tail -n +2 testfile > /dev/null; done
real    0m7.485s
user    0m0.292s
sys     0m6.020s如您所见,时间安排非常相似,没有太多需要解释或怀疑的地方。对于小文件,两种工具都同样适用。
awk也可以做到这一点。我最初的问题基于我首先找到的链接。你所有的努力后请告知我是否应该删除awk的解决方案候选人,焦点返回到只有原来的项目范围sed和tail。
                    awk 'NR > 1'很有趣)。
                    这是另一种选择,仅使用bash内置函数和cat:
{ read ; cat > headerless.txt; } < $file$file重定向到{ }命令分组。在read简单的读取和丢弃的第一道防线。然后将流的其余部分通过管道传输到cat该流,并将其写入目标文件。
在我的Ubuntu 16.04上,其性能和tail解决方案非常相似。我使用以下命令创建了一个比较大的测试文件seq:
$ seq 100000000 > 100M.txt
$ ls -l 100M.txt 
-rw-rw-r-- 1 ubuntu ubuntu 888888898 Dec 20 17:04 100M.txt
$tail 解:$ time tail -n +2 100M.txt > headerless.txt
real    0m1.469s
user    0m0.052s
sys 0m0.784s
$ cat/括号解决方案:$ time { read ; cat > headerless.txt; } < 100M.txt 
real    0m1.877s
user    0m0.000s
sys 0m0.736s
$ 我现在只有一台Ubuntu VM,虽然两者都在同一范围内,但是两者的时间却有很大差异。
tail但仍然认为该read选项非常酷。
                    在我的系统上进行尝试,并在每个命令前面加上time以下命令,结果如下:
sed:
real    0m0.129s
user    0m0.012s
sys     0m0.000s和尾巴:
real    0m0.003s
user    0m0.000s
sys     0m0.000s这表明,在我的系统上至少运行Ubuntu 16.04的AMD FX 8250上,tail的速度明显更快。测试文件有10,000行,大小为540k。从硬盘读取文件。
sed可能会在此结果中起作用,这就是您对其进行测试的顺序
                    sed速度大约是以前的两倍。
                    没有客观的方法可以说哪个更好,因为在程序执行过程中,sed并且tail不是唯一在系统上运行的东西。许多因素,例如磁盘I / O,网络I / O,较高优先级进程的CPU中断-所有这些因素都会影响程序的运行速度。
两者都是用C编写的,因此这不是语言问题,而是环境问题。例如,我有SSD,而在我的系统上这将花费数微秒的时间,但是对于硬盘上的相同文件,则将花费更多的时间,因为HDD的速度明显降低。因此,硬件也起着重要作用。
在考虑选择哪个命令时,您可能需要记住以下几点:
sed是用于转换文本的流编辑器。tail用于输出特定的文本行。如果要处理线条而仅将其打印出来,请使用tail。如果要编辑文本,请使用sed。tail语法比的简单得多sed,因此请使用您自己可以阅读的内容以及他人可以阅读的内容。另一个重要因素是您正在处理的数据量。小文件不会给您带来任何性能差异。处理大文件时,图片变得很有趣。使用2 GB的BIGFILE.txt,我们可以看到它的sed系统调用数量比得多tail,并且运行速度也慢得多。
bash-4.3$ du -sh BIGFILE.txt 
2.0G    BIGFILE.txt
bash-4.3$ strace -c  sed '1d' ./BIGFILE.txt  > /dev/null
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 59.38    0.079781           0    517051           read
 40.62    0.054570           0    517042           write
  0.00    0.000000           0        10         1 open
  0.00    0.000000           0        11           close
  0.00    0.000000           0        10           fstat
  0.00    0.000000           0        19           mmap
  0.00    0.000000           0        12           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         2           rt_sigaction
  0.00    0.000000           0         1           rt_sigprocmask
  0.00    0.000000           0         1         1 ioctl
  0.00    0.000000           0         7         7 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           getrlimit
  0.00    0.000000           0         2         2 statfs
  0.00    0.000000           0         1           arch_prctl
  0.00    0.000000           0         1           set_tid_address
  0.00    0.000000           0         1           set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00    0.134351               1034177        11 total
bash-4.3$ strace -c  tail  -n +2 ./BIGFILE.txt  > /dev/null
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 62.30    0.148821           0    517042           write
 37.70    0.090044           0    258525           read
  0.00    0.000000           0         9         3 open
  0.00    0.000000           0         8           close
  0.00    0.000000           0         7           fstat
  0.00    0.000000           0        10           mmap
  0.00    0.000000           0         4           mprotect
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         3           brk
  0.00    0.000000           0         1         1 ioctl
  0.00    0.000000           0         3         3 access
  0.00    0.000000           0         1           execve
  0.00    0.000000           0         1           arch_prctl
------ ----------- ----------- --------- --------- ----------------
100.00    0.238865                775615         7 totaltail得更好sed-请使用。我个人会使用python或awk而不是sed因为它会变得复杂。此外,如果您担心性能,让我们面对现实-您在这里看到的结果以微秒为单位。除非它是您要读取的千兆字节级的巨大文件,否则您不会感到与众不同
                    awk答案:)...我的问题是基于另一个AU Q&A(在链接中),在那里他们从未提及awk。我同意时间差异在小文件上是正常的。我只是想养成一些好习惯。
                    awk 'NR!=1' input_file.txt 。它给我同样的结果,大约150毫秒,tail和都相同sed。但是,我正在使用SSD,所以我要说的是硬盘和CPU至关重要,而不是命令。
                    sed耗时超过3分钟,而tail仅需要20秒左右。实际上那还不是很大,绝对不在GB范围内。
                    最佳答案未将磁盘考虑在内 > /dev/null
如果文件很大,又不想在磁盘上创建临时副本,请尝试 vim -c 
$ cat /dev/urandom | base64 -w0 | tr 'n' '\n'| head -n 10000000 > testfile
$ time sed -i '1d' testfile
real    0m59.053s
user    0m9.625s
sys     0m48.952s
$ cat /dev/urandom | base64 -w0 | tr 'n' '\n'| head -n 10000000 > testfile
$ time vim -e -s testfile -c ':1d' -c ':wq'
real    0m8.259s
user    0m3.640s
sys     0m3.093s编辑:如果文件大于可用内存vim -c不起作用,则表明它不够智能,无法增量加载文件
sed是更可移植的:“ +2”表示tail在使用GNU的Ubuntu上工作正常tail,但在BSD上不起作用tail。