我需要使用bash脚本从巨大的文本文件中反复删除第一行。
现在,我正在使用sed -i -e "1d" $FILE
但删除它大约需要一分钟。
有没有更有效的方法来实现这一目标?
#1楼
您可以就地编辑文件:只需使用perl的-i
标志,如下所示:
perl -ni -e 'print unless $. == 1' filename.txt
根据您的要求,这使得第一行消失了。 Perl将需要读取和复制整个文件,但是它安排将输出保存为原始文件的名称。
#2楼
对于使用非GNU的SunOS的用户,以下代码将有所帮助:
sed '1d' test.dat > tmp.dat
#3楼
如果您要执行的操作是在失败后恢复,则可以建立一个具有到目前为止已完成操作的文件。
if [[ -f $tmpf ]] ; then
rm -f $tmpf
fi
cat $srcf |
while read line ; do
# process line
echo "$line" >> $tmpf
done
#4楼
您可以使用-i来更新文件,而无需使用’>’运算符。 以下命令将从文件中删除第一行并将其保存到文件中。
sed -i '1d' filename
#5楼
不,这与您将要获得的效率差不多。 您可以编写一个C程序,该程序可以更快地完成工作(更少的启动时间和处理参数),但是随着文件变大,它可能趋向于与sed相同的速度(如果花一分钟,我认为它们会变大) )。
但是您的问题与其他许多问题一样面临着同样的问题,因为它以解决方案为先决条件。 如果你要告诉我们详细你想要做而不是什么 怎么样 ,我们也许能够提出更好的选择。
例如,如果这是其他程序B处理的文件A,则一种解决方案是不剥离第一行,而修改程序B以不同方式处理它。
假设您的所有程序都附加到此文件A,并且程序B当前在删除第一行之前对其进行读取和处理。
您可以重新设计程序B,以便它不会尝试删除第一行,而是在文件A中保留一个持久的(可能是基于文件的)偏移量,以便在下次运行时可以查找该偏移量,然后进行处理。那里的线,并更新偏移量。
然后,在安静的时间(午夜?),它可以对文件A进行特殊处理,以删除当前处理的所有行并将偏移量设置回0。
程序打开并查找文件肯定比打开并重写更快。 当然,该讨论假定您具有对程序B的控制权。 我不知道是这种情况,但是如果您提供更多信息,可能还有其他可能的解决方案。
#6楼
由于听起来我无法加快删除速度,所以我认为一种好的方法可能是按以下方式批量处理文件:
While file1 not empty
file2 = head -n1000 file1
process file2
sed -i -e "1000d" file1
end
这样做的缺点是,如果程序在中间被杀死(或者如果其中有一些不好的sql,导致“进程”部分死亡或锁定),则会跳过或处理两次行。
(file1包含几行sql代码)
#7楼
正如Pax所说,您可能不会比这更快。 原因是几乎没有文件系统支持从文件开头截断,因此这将是一个O( n
)操作,其中n
是文件的大小。 你可以做什么,虽然速度更快是覆盖具有相同的字节数(也许用空格或注释),这可能会为您取决于正是你正在尝试做的工作第一线(那是什么来着?)。
#8楼
是否会在N-1行上使用tail并将其定向到文件中,然后删除旧文件,然后将新文件重命名为旧名称呢?
如果我以编程方式执行此操作,则在读取每一行后,我将通读文件,并记住文件偏移量,因此我可以返回该位置以读取其中少一行的文件。
#9楼
试试tail :
tail -n +2 "$FILE"
-nx
:仅打印最后的x
行。 tail -n 5
将为您提供输入的最后5行。 +
号可以反转参数,并使tail
打印除x-1
行以外的任何内容。 tail -n +1
会打印整个文件, tail -n +2
会打印除第一行以外的所有内容, tail -n +2
。
GNU的tail
比sed
快得多。 在BSD上也可以使用tail
,并且-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
- 壳牌为
tail
创建新流程 - Shell将
tail
进程的标准输出重定向到$FILE
-
tail
从现在为空的$FILE
读取
如果要删除文件中的第一行,则应使用:
tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
&&
将确保出现问题时不会覆盖文件。
#10楼
sponge
避免了处理临时文件的需要:
tail -n +2 "$FILE" | sponge "$FILE"
#11楼
应该显示第一行以外的行:
cat textfile.txt | tail -n +2
#12楼
可以使用vim来做到这一点:
vim -u NONE +'1d' +'wq!' /tmp/test.txt
这应该更快,因为vim在处理时不会读取整个文件。
#13楼
如果要修改到位的文件,你总是可以使用原始ed
,而不是以S treaming接班人sed
:
ed "$FILE" <<<$'1d\nwq\n'
ed
命令是原始的UNIX文本编辑器,甚至没有全屏终端,而图形工作站则少得多。 的ex
主编,最有名的是你用什么在结肠提示符下键入时vi
,是一个前趋于版ed
,所以很多相同的命令工作的。 尽管ed
旨在交互使用,但也可以通过向其发送一串命令而以批处理方式使用它,这是此解决方案的作用。
序列<<<$'1d\\nwq\\n'
充分利用了Bash对here-string( <<<
)和POSIX引号( $'
… '
)的支持,将输入提供给ed
命令,该命令由两行组成: 1d
, 其中详细eletes线1,然后wq
,其中W仪式文件回到磁盘和则q UITS编辑会话。
#14楼
您可以轻松地做到这一点:
cat filename | sed 1d > filename_without_first_line
在命令行上; 或要永久删除文件的第一行,请使用带有-i
标志的sed就地模式:
sed -i 1d <filename>
#15楼
如何使用csplit?
man csplit
csplit -k file 1 '{1}'