如何使用 Bash 和标准实用程序确定两个字符串之间的行数?

How to determine number of lines between two strings using Bash and standard utilities?

我有一个包含如下数据的文件:

abc
abc, Iteration 1
abc
abc, Iteration 2
...
abc
abc, Iteration 19
abc
abc, Iteration 20

我想确定恰好以字符串 "Iteration 1" 和 "Iteration 2" 结束的行之间的行数,并将行数存储到变量 numlines。在上面的示例中,numlines 应包含值 1。

我想使用 wc -lsedawk

sed '/Iteration\ 1/,/Iteration\ 2/!d;//d' filename  | wc -l

简洁,但总是处理 整个 输入文件 (并且还会创建额外的子进程,因为 wc -l 也必须被调用——尽管这在总体上无关紧要)。

尝试以下 awk 解决方案一旦找到范围的末尾(它也只创建一个子进程 - 子 shell 被优化以支持简单的 awk 命令);对于大的输入文件,这可能很重要,具体取决于范围在文件中的位置:

numlines=$(awk '/Iteration 1$/ {b=NR; next} /Iteration 2$/ {print NR-b-1; exit}' file)

感谢karakfa帮助优化命令。

注意:/Iteration 1$//Iteration 2$/匹配字符串Iteration 1Iteration 2的正则表达式在行尾 ($).
手头的字符串恰好不包含需要转义的正则表达式元字符(使用 \),但在其他情况下您可能必须这样做。
如果要匹配的字符串不是事先已知的文字,则通用转义将很困难;在这种情况下,考虑 ,它基于 strings,而不是正则表达式。

目前所有的解决方案都使用正则表达式,而不是字符串,因此当您的字符串包含 RE 元字符时将会失败。这是如何按照您在问题中要求的那样使用字符串执行您想要的操作:

$ awk '
BEGIN  {
    begStr = "Iteration 1"
    endStr = "Iteration 2"
}
index([=10=],begStr) == 1 + length([=10=]) - length(begStr) { begNr = NR }
index([=10=],endStr) == 1 + length([=10=]) - length(endStr) { print NR - begNr - 1 }
' file
1