如何使用 sed 从文件开头打印到所有匹配元素。文件大小大于 25GB

How to use sed to print from the beginning of the file till all the matching elements. The file size is greater than 25GB

我无法使用 sed 从头开始​​打印文件的内容,直到找到匹配的模式,当它找到第一次出现的模式时它停止并且不打印所有匹配的模式。

因为文件大小大于25GB。但是,下面是问题的一个小例子。

例:文件内容为:

2010T10:11:12 some data.
2012T10:11:12 some data.
2013T10:11:12 They all are different data
2014T10:11:12 Logs basically
2014T10:11:12 Error Logs
2014T10:11:12 Any Data
2014T10:11:12 Data
2015T10:11:12 Some fields
2016T10:11:12 etc

基本上,当我给出从 2010T10:11:12 - 2014T10:11:12 的范围时,它应该打印到文件的第 7 行。

我使用的打印命令是:

sed -n '1,/2014T10:11:12/p' File-1.txt

输出:

2010T10:11:12 some data.
2012T10:11:12 some data.
2013T10:11:12 They all are different data
2014T10:11:12 Logs basically

预期输出:

2010T10:11:12 some data.
2012T10:11:12 some data.
2013T10:11:12 They all are different data
2014T10:11:12 Logs basically
2014T10:11:12 Error Logs
2014T10:11:12 Any Data
2014T10:11:12 Data

此命令复制匹配模式的第一行:

sed -n '1,/2014T10:11:12/p;/2014T10:11:12/p' File-1.txt

输出:

2010T10:11:12 some data.
2012T10:11:12 some data.
2013T10:11:12 They all are different data
2014T10:11:12 Logs basically <- Duplicate line. Need to
2014T10:11:12 Logs basically <- remove any one of them
2014T10:11:12 Error Logs
2014T10:11:12 Any Data
2014T10:11:12 Data

另一个问题是文件的内容每秒都在变化,所以我们不能给出任何范围,如 1-7 或 5-7。它必须基于 2010T10:11:12 - 2014T10:11:12 或 2015T10:11:12 - 2016T10:11:12.

这样的模式

试试这个:

awk '( >= "2010T10:11:12") && ( <= "2014T10:11:12")' File-1.txt

awk 的替代版本是:

awk '( > "2014T10:11:12"){exit}1' file

这在处理大文件时很有用,因为当第一个字段的字典顺序大于“2014T10:11:12”时它将停止读取文件。

如果你想打印一个范围,你可以这样做:

awk '( > "2014T10:11:12"){exit}( >= "2013T12:12:12")' file

当您想过度优化它时:

awk '( >= "2013T12:12:12") { if( > "2014T10:11:12"){exit}; print}' file

这有效。

sed -n '1,/2014T10:11:12/{p;d}; /2014T10:11:12/{p;d}; q' File-1.txt

在此处阅读有关 sed 的 dq 命令的信息:https://www.gnu.org/software/sed/manual/sed.html#Common-Commands

您需要 sed 中的地址范围:

begin='^2010T10:11:12'
end='^2014T10:11:12'

sed -n "
    /$begin/,/$end/{ p; d; }
    /$end/p
" file

这假定输入文件按第一个字段(日期和时间)排序。
需要第二个命令 (/$end/p),因为您要打印 所有 行匹配 $end。范围地址 (/$begin/,/$end/) 匹配从 $begin 匹配处开始的行,并一直持续到 第一个 匹配 $end 的行(包括)。

下面的代码可能更有效率,因为它在匹配 $end 的最后一行后放弃读取输入(输入必须排序才能工作)。

begin='^2010T10:11:12'
end='^2014T10:11:12'

sed -n "
    /$begin/,/$end/{
        /$end/{
            :a
            p
            n
            /$end/!q
            ba
        }
        p
    }
" file