目前我正在使用sed来打印文件的所需部分。例如,我使用了以下命令
sed -n 89001,89009p file.xyz
但是,随着文件大小的增加,它的速度非常慢(我的文件目前为6.8 GB)。我试图遵循这个link并使用命令
sed -n '89001,89009{p;q}' file.xyz
但是,此命令仅打印第89001行。请帮助我。
答案 0 :(得分:7)
语法略有不同:
sed -n '89001,89009p;89009q' file.xyz
<强>更新强>
由于还有 awk 的答案,我做了一个小比较,正如我想的那样 - sed 更快一点:
$ wc -l large-file
100000000 large-file
$ du -h large-file
954M large-file
$ time sed -n '890000,890010p;890010q' large-file > /dev/null
real 0m0.141s
user 0m0.068s
sys 0m0.000s
$ time awk 'NR>=890000{print} NR==890010{exit}' large-file > /dev/null
real 0m0.433s
user 0m0.208s
sys 0m0.008s`
<强> UPDATE2:强>
由@EdMorton发布的 awk 有一种更快的方式,但仍然没有 sed 那么快:
$ time awk 'NR>=890000{print; if (NR==890010) exit}' large-file > /dev/null
real 0m0.252s
user 0m0.172s
sys 0m0.008s
<强>更新强>
这是我能找到的最快的方式(头和尾):
$ time head -890010 large-file| tail -10 > /dev/null
real 0m0.085s
user 0m0.024s
sys 0m0.016s
答案 1 :(得分:4)
awk 'NR>=89001{print; if (NR==89009) exit}' file.xyz
答案 2 :(得分:2)
在awk中更易于阅读,性能应与sed
awk 'NR>=89001{print} NR==89009{exit}' file.xyz
您也可以用分号替换{print}
。
答案 3 :(得分:2)
Dawid Grabowski's helpful answer是可行的方法(sed
[1]
; Ed Morton's helpful answer是一种可行的awk
替代方案; tail
+ head
组合通常是最快的 [2] 。
至于为什么你的方法不起作用:
89001,89009
这样的双地址表达式选择一个包含范围的行,以起始和结束地址为界(在本例中为行号)。
然后为所选范围内的每一行执行相关的功能列表{p;q;}
。
因此,第#行89001
是导致函数列表执行的第一行:在打印(p
)之后,行执行函数q
- 退出执行马上,没有处理任何其他行。
为了防止过早退出,Dawid的答案因此将打印(p
)范围内的所有行与退出(q
)处理分开,使用两个用;
分隔的命令:
89001,89009p
打印范围89009q
在达到范围的终点时退出处理 [1]重复性稍差的重新制定应该同样表现良好($
代表 last 行,由于第二个命令而永远不会达到这一点:
sed -n '89001,$ p; 89009 q'
功能
[2]从Dawid的回答中更好地重新阐述head
+ tail
解决方案是
tail -n +89001 file | head -n 9
,因为它限制了感兴趣的不的字节数,但仍然以管道缓冲区大小通过管道发送(典型的管道缓冲区大小为64 KB)。
使用 GNU 实用程序(Linux),这是最快的解决方案,但在具有库存实用程序(BSD)的OSX上,sed
解决方案最快。
答案 4 :(得分:0)
另一种方法是使用 head 和 tail 的组合:
$ time head -890010 large-file| tail -10 > /dev/null
real 0m0.085s
user 0m0.024s
sys 0m0.016s
这比 sed 和 awk 更快。
答案 5 :(得分:-2)
需要 sed 从文件的开头搜索才能找到第N行。为了加快速度,请使用和索引文件以固定行数间隔划分大文件。然后使用 dd 跳过大文件的早期部分,然后转到 sed 。
使用以下方法构建索引文件:
#!/bin/bash
INTERVAL=1000
LARGE_FILE="big-many-GB-file"
INDEX_FILE="index"
LASTSTONE=123
MILESTONE=0
echo $MILESTONE > $INDEX_FILE
while [ $MILESTONE != $LASTSTONE ] ;do
LASTSTONE=$MILESTONE
MILESTONE=$(dd if="$LARGE_FILE" bs=1 skip=$LASTSTONE 2>/dev/null |head -n$INTERVAL |wc -c)
MILESTONE=$(($LASTSTONE+$MILESTONE))
echo $MILESTONE >> $INDEX_FILE
done
exit
然后使用:./ this_script.sh 89001
搜索一行#!/bin/bash
INTERVAL=1000
LARGE_FILE="big-many-GB-file"
INDEX_FILE="index"
LN=$(($1-1))
OFFSET=$(head -n$((1+($LN/$INTERVAL))) $INDEX_FILE |tail -n1)
LN=$(($LN-(($LN/$INTERVAL)*$INTERVAL)))
LN=$(($LN+1))
dd if="$LARGE_FILE" bs=1 skip=$OFFSET 2>/dev/null |sed -n "$LN"p