我需要使用bash脚本从一个巨大的文本文件中反复删除第一行。

现在我正在使用sed - I -e "1d" $FILE -但它需要大约一分钟的时间来删除。

有没有更有效的方法来实现这个目标?


当前回答

正如帕克斯所说,你可能不会比这更快。原因是几乎没有文件系统支持从文件的开头截断,所以这将是一个O(n)操作,其中n是文件的大小。不过,您可以更快地做的是用相同数量的字节(可能是空格或注释)覆盖第一行,这可能对您有用,具体取决于您正在尝试做什么(顺便说一下,这是什么?)

其他回答

试着尾巴:

tail -n +2 "$FILE"

-n x:只打印最后x行。Tail - n5表示输入的最后5行。+号有点颠倒了参数,使tail打印除第一个x-1行以外的任何内容。尾部-n +1输出整个文件,尾部-n +2输出除第一行以外的所有内容,等等。

GNU tail比sed快得多。tail在BSD上也可用,并且-n +2标志在这两个工具中是一致的。查看FreeBSD或OS X手册页了解更多信息。

不过,BSD版本可能比sed慢得多。我不知道他们是怎么做到的;Tail应该只是逐行读取文件,而sed则执行相当复杂的操作,包括解释脚本、应用正则表达式等。

注意:您可能会忍不住使用

# THIS WILL GIVE YOU AN EMPTY FILE!
tail -n +2 "$FILE" > "$FILE"

但这将给您一个空文件。原因是重定向(>)发生在shell调用tail之前:

Shell截断文件$ file Shell为tail创建一个新进程 Shell将尾部进程的stdout重定向到$FILE tail从现在空的$FILE中读取

如果你想删除文件中的第一行,你应该使用:

tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"

&&将确保当出现问题时文件不会被覆盖。

使用split怎么样?

man csplit
csplit -k file 1 '{1}'

海绵util避免了对临时文件的杂耍:

tail -n +2 "$FILE" | sponge "$FILE"

对于那些使用非gnu的SunOS的人来说,下面的代码将会有所帮助:

sed '1d' test.dat > tmp.dat 

可以使用sed命令按行号删除任意行

# create multi line txt file
echo """1. first
2. second
3. third""" > file.txt

删除行并打印到标准输出

$ sed '1d' file.txt 
2. second
3. third

$ sed '2d' file.txt 
1. first
3. third

$ sed '3d' file.txt 
1. first
2. second

# delete multi lines
$ sed '1,2d' file.txt 
3. third

# delete the last line
sed '$d' file.txt 
1. first
2. second

使用-i选项就地编辑文件

$ cat file.txt 
1. first
2. second
3. third

$ sed -i '1d' file.txt

$cat file.txt 
2. second
3. third