逐行读取文件并记住文件中的最后位置

逐行读取文件并记住文件中的最后位置

我想使用另一个文件的输入来 grep 日志文件中的某些行。我正在使用这个小命令来做到这一点:

while read line; do 
    grep "$line" service.log; 
done < input_strings.txt > result.txt

input_strings.txt有大约 50 000 个字符串(每行一个)。对于这个字符串中的每一个,我当前正在搜索巨大的service.log文件(大约有 2 000 000 行)。

假设第一个字符串是在第 10 000 行input_strings.txt找到的,这一行被写入到我的.之后,将在 中搜索 的第二个字符串,但从 的第 1 行开始。service.logresult.txtinput_strings.txtservice.logservice.log

我如何记住在 中找到第一个条目的最后一行service.log?这样我就可以在那里开始第二次搜索运行?

答案1

如果你想获得匹配,那么你根本不需要使用循环。仅使用单个命令会快得多grep

grep -Ff input_strings service.log > results.txt

也就是说,如果您想按字面意思执行问题中所述的操作,那么您可以使用变量来跟踪找到最后一个匹配项的行:

LINE_NUMBER=0
while read LINE; do

    # Search for the next match starting at the line number of the previous match
    MATCH="$(tail -n+${LINE_NUMBER} "service.log" | grep -n "${LINE}" | head -n1)";

    # Extract the line number from the match result
    LINE_NUMBER="${MATCH/:*/}";

    # Extract the matching string from the match result
    STRING="${x#*:}";

    # Output the matching string
    echo "${STRING}";

done < input_strings.txt > result.txt

答案2

我猜你想搜索第一个关键字,然后在该匹配之后继续搜索下一个关键字等,并打印匹配的内容。

鉴于keywords

foo
bar

data

bar 0
foo 1
bar 1
foo 2

这里的脚本awk应该做到这一点(使用 GNU awk 测试):

$ awk 'BEGIN {i = j = 0} NR==FNR { k[i++] = $0; next} 
       $0 ~ k[j] {j++; print $0} j >= i {exit}' keywords data 
foo 1
bar 1

i从 0开始j,在第一个文件期间(将NR==FNR当前文件的记录/行号与所看到的总行数进行比较),我们将关键字收集到一个数组中。之后,尝试匹配j:th 关键字,并j在匹配时打印并增加。找到所有关键字后退出。

与 一样grep,这里的关键字实际上是正则表达式模式,尽管awk这里显然是正则表达式。如果您想搜索固定字符串,请使用index($0, key)代替$0 ~ key


或者,在开始时不加载关键字:

$ awk -vkeyfile=keywords 'BEGIN {getline key < keyfile } 
      $0 ~ key {print $0; if (!getline key < keyfile) exit;}' data
foo 1 
bar 1

这应该很简单。

相关内容