bash - 如何删除文本文件中长度大于 1GB 的所有行?
问题描述
我有一个可能包含长行的文本文件。如何删除该文件中长度超过 1GB 的所有行,只保留小于 1GB 的行?谢谢
解决方案
我相信您的问题的任何解决方案都需要多次读取文件或将行读取到至少 1GB 大的缓冲区中。
bash 中的一个幼稚的解决方案是后者,并且可能会崩溃:
#!/bin/bash
while IFS= read -r line; do
if [ ${#line} -le 1000000000 ]; then
echo "$line"
fi
done <infile >tmpfile
mv tmpfile infile
它会运行得非常慢,从快速测试来看,我认为它需要的内存是最长线路的 3 倍。
我们可以读入一个较小的缓冲区来避免这种情况,但代码要复杂得多,而且运行速度仍然非常慢。例如:
#!/bin/bash
max=1000000000
buflen=33554432
len=0
data="$(tempfile)"
savedata(){
printf "%s" "$1" >>"$data"
(( len+=${#1} ))
}
cleardata(){
cat /dev/null >"$data"
len=0
}
maybeprintdata(){
if (( len<max )); then
cat "$data"
(( noecho )) || echo
fi
}
(
while IFS= read -n $buflen -r line || [ -n "$line" ]; do
savedata "$line"
if (( ${#line}!=buflen )); then
maybeprintdata
cleardata
fi
done
(( len )) && noecho=1 maybeprintdata
) <infile >tmpfile
mv tmpfile infile
rm "$data"
如果您不限于 bash,则可以使用更快的程序。
与朴素 bash 解决方案等效的“单线”Perl 可能是:
perl -i -nlE 'length>1e9 || say' file
-i
file
就地进行更改-n
在程序周围包装一个隐式迭代行循环1e9
是 1000000000 的简写形式say
就像bash的echo
请注意,与上面“复杂”的 bash 程序不同,这个简单的 Perl 程序会输出最后一个换行符,即使输入没有换行符。
另请注意,它需要与最长文件行一样多的 RAM(如果行长可能超过内存,这可能是一个问题)。
推荐阅读
- windows - 我们可以在 Xamarin UWP(Windows 移动应用程序)中使用 Windows UI 库吗
- .net - .net 框架中是否有任何本地化常量,如“今天”、“明天”、“昨天”等
- c++ - 为什么模板函数接受左值与右值引用绑定?
- cmake - 包含生成器表达式的列表无效
- python - 将消息从 telegram.bot 移动到 aws-RabbitMQ
- python - 执行 Try/Except 时出错
- components - 是否可以在开放 API 定义中“分组”可重用组件?
- python - 如何找出字符串的两个相等部分是否是python中的字谜
- scala - 递归期间Scala中的flatMap()
- python - Pandas - 在 pandas 应用函数中获取行的索引