我需要使用bash脚本从一个巨大的文本文件中重复删除第一行 .
现在我正在使用 sed -i -e "1d" $FILE - 但删除大约需要一分钟 .
sed -i -e "1d" $FILE
有没有更有效的方法来实现这一目标?
用csplit怎么样?
man csplit csplit -k file 1 '{1}'
由于听起来我无法加速删除,我认为一个好的方法可能是批量处理文件,如下所示:
While file1 not empty file2 = head -n1000 file1 process file2 sed -i -e "1000d" file1 end
这样做的缺点是,如果程序在中间被杀死(或者如果那里有一些不好的sql - 导致“进程”部分死亡或锁定),则会有跳过或被处理两次的行 .
(file1包含sql代码行)
如果要修改文件,可以始终使用原始 ed 而不是 s treaming successor sed :
ed
sed
ed "$FILE" <<<$'1d\nwq\n'
您可以使用-i更新文件,而无需使用“>”运算符 . 以下命令将从文件中删除第一行并将其保存到文件中 .
sed -i '1d' filename
不,这就像你要获得的那样高效 . 你可以编写一个C程序,它可以更快地完成工作(减少启动时间和处理参数)但它可能会趋向于与文件变大的sed相同的速度(并且我认为如果需要一分钟,它们会很大) .
但是你的问题与许多其他问题一样,因为它预先设定了解决方案 . 如果你要详细告诉我们 what 你试图做的事情,而不是 how ,我们可能会建议一个更好的选择 .
例如,如果这是某个其他程序B处理的文件A,则一种解决方案是不剥离第一行,而是修改程序B以不同方式处理它 .
假设所有程序都附加到此文件A,程序B当前在删除它之前读取并处理第一行 .
您可以重新设计程序B,以便它不会尝试删除第一行但是在文件A中保持一个持久的(可能是基于文件的)偏移量,以便下次运行时可以寻找该偏移量,进程那里的线,并更新偏移量 .
然后,在安静的时间(午夜?),它可以对文件A进行特殊处理,以删除当前处理的所有行,并将偏移量设置回0 .
程序打开和查找文件而不是打开和重写肯定会更快 . 当然,本讨论假定您可以控制程序B.我不知道是否是这种情况,但如果您提供进一步的信息,可能还有其他可能的解决方案 .
应显示除第一行以外的行:
cat textfile.txt | tail -n +2
你可以轻松地做到这一点:
cat filename | sed 1d > filename_without_first_line
在命令行上;或者永久删除文件的第一行,使用带有 -i 标志的sed就地模式:
-i
sed -i 1d <filename>
可以使用vim来做到这一点:
vim -u NONE +'1d' +'wq!' /tmp/test.txt
这应该更快,因为vim在处理时不会读取整个文件 .
试试GNU tail:
tail -n +2 "$FILE"
-n x :只需打印最后的 x 行 . tail -n 5 将为您提供输入的最后5行 . + 符号反转参数并使 tail 打印除第一个 x-1 行以外的任何内容 . tail -n +1 将打印整个文件, tail -n +2 除第一行外的所有内容等 .
-n x
x
tail -n 5
+
tail
x-1
tail -n +1
tail -n +2
GNU tail 比 sed 快得多 . tail 也可用于BSD, -n +2 标志在两个工具中都是一致的 . 查看FreeBSD或OS X手册页以获取更多信息 .
-n +2
但是,BSD版本可能比 sed 慢得多 . 我想知道他们是如何做到的; tail 应该只是逐行读取文件,而 sed 执行相当复杂的操作,包括解释脚本,应用正则表达式等 .
注意:您可能很想使用
# THIS WILL GIVE YOU AN EMPTY FILE! tail -n +2 "$FILE" > "$FILE"
但这会给你一个 empty file . 原因是重定向( > )发生在shell调用 tail 之前:
>
Shell截断文件 $FILE
$FILE
Shell为 tail 创建一个新进程
Shell将 tail 进程的stdout重定向到 $FILE
tail 从现在空的 $FILE 读取
如果要删除文件中的第一行,则应使用:
tail -n +2 "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
&& 将确保在出现问题时不会覆盖该文件 .
&&
你 can 编辑文件:只需使用perl的 -i 标志,如下所示:
perl -ni -e 'print unless $. == 1' filename.txt
这会使第一行消失,正如你所问的那样 . Perl需要读取和复制整个文件,但它会安排输出以原始文件的名称保存 .
对于那些使用非GNU的SunOS的人,以下代码将有所帮助:
sed '1d' test.dat > tmp.dat
如果你想要做的是在失败后恢复,你可以 Build 一个具有你迄今为止所做的事情的文件 .
if [[ -f $tmpf ]] ; then rm -f $tmpf fi cat $srcf | while read line ; do # process line echo "$line" >> $tmpf done
正如Pax所说,你可能不会比这更快 . 原因是那里几乎没有支持从文件开头截断的文件系统,所以这将是一个O( n )操作,其中 n 是文件的大小 . 你可以做得更快但是用相同的字节数(可能带空格或注释)覆盖第一行,这可能对你有用,具体取决于你想要做什么(顺便说一句是什么?) .
n
会在N-1行上使用tail并将其导入文件,然后删除旧文件,并将新文件重命名为旧名称吗?
如果我以编程方式执行此操作,我会读取文件,并在读取每一行后记住文件偏移量,因此我可以回到该位置以读取文件中少一行 .
sponge util避免了玩杂耍临时文件的需要:
tail -n +2 "$FILE" | sponge "$FILE"
15 回答
用csplit怎么样?
由于听起来我无法加速删除,我认为一个好的方法可能是批量处理文件,如下所示:
这样做的缺点是,如果程序在中间被杀死(或者如果那里有一些不好的sql - 导致“进程”部分死亡或锁定),则会有跳过或被处理两次的行 .
(file1包含sql代码行)
如果要修改文件,可以始终使用原始
ed
而不是 s treaming successorsed
:您可以使用-i更新文件,而无需使用“>”运算符 . 以下命令将从文件中删除第一行并将其保存到文件中 .
不,这就像你要获得的那样高效 . 你可以编写一个C程序,它可以更快地完成工作(减少启动时间和处理参数)但它可能会趋向于与文件变大的sed相同的速度(并且我认为如果需要一分钟,它们会很大) .
但是你的问题与许多其他问题一样,因为它预先设定了解决方案 . 如果你要详细告诉我们 what 你试图做的事情,而不是 how ,我们可能会建议一个更好的选择 .
例如,如果这是某个其他程序B处理的文件A,则一种解决方案是不剥离第一行,而是修改程序B以不同方式处理它 .
假设所有程序都附加到此文件A,程序B当前在删除它之前读取并处理第一行 .
您可以重新设计程序B,以便它不会尝试删除第一行但是在文件A中保持一个持久的(可能是基于文件的)偏移量,以便下次运行时可以寻找该偏移量,进程那里的线,并更新偏移量 .
然后,在安静的时间(午夜?),它可以对文件A进行特殊处理,以删除当前处理的所有行,并将偏移量设置回0 .
程序打开和查找文件而不是打开和重写肯定会更快 . 当然,本讨论假定您可以控制程序B.我不知道是否是这种情况,但如果您提供进一步的信息,可能还有其他可能的解决方案 .
应显示除第一行以外的行:
你可以轻松地做到这一点:
在命令行上;或者永久删除文件的第一行,使用带有
-i
标志的sed就地模式:可以使用vim来做到这一点:
这应该更快,因为vim在处理时不会读取整个文件 .
试试GNU tail:
-n x
:只需打印最后的x
行 .tail -n 5
将为您提供输入的最后5行 .+
符号反转参数并使tail
打印除第一个x-1
行以外的任何内容 .tail -n +1
将打印整个文件,tail -n +2
除第一行外的所有内容等 .GNU
tail
比sed
快得多 .tail
也可用于BSD,-n +2
标志在两个工具中都是一致的 . 查看FreeBSD或OS X手册页以获取更多信息 .但是,BSD版本可能比
sed
慢得多 . 我想知道他们是如何做到的;tail
应该只是逐行读取文件,而sed
执行相当复杂的操作,包括解释脚本,应用正则表达式等 .注意:您可能很想使用
但这会给你一个 empty file . 原因是重定向(
>
)发生在shell调用tail
之前:Shell截断文件
$FILE
Shell为
tail
创建一个新进程Shell将
tail
进程的stdout重定向到$FILE
tail
从现在空的$FILE
读取如果要删除文件中的第一行,则应使用:
&&
将确保在出现问题时不会覆盖该文件 .你 can 编辑文件:只需使用perl的
-i
标志,如下所示:这会使第一行消失,正如你所问的那样 . Perl需要读取和复制整个文件,但它会安排输出以原始文件的名称保存 .
对于那些使用非GNU的SunOS的人,以下代码将有所帮助:
如果你想要做的是在失败后恢复,你可以 Build 一个具有你迄今为止所做的事情的文件 .
正如Pax所说,你可能不会比这更快 . 原因是那里几乎没有支持从文件开头截断的文件系统,所以这将是一个O(
n
)操作,其中n
是文件的大小 . 你可以做得更快但是用相同的字节数(可能带空格或注释)覆盖第一行,这可能对你有用,具体取决于你想要做什么(顺便说一句是什么?) .会在N-1行上使用tail并将其导入文件,然后删除旧文件,并将新文件重命名为旧名称吗?
如果我以编程方式执行此操作,我会读取文件,并在读取每一行后记住文件偏移量,因此我可以回到该位置以读取文件中少一行 .
sponge util避免了玩杂耍临时文件的需要: