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

时间:2016-10-12 01:59:20

标签: linux bash awk sed wc

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

application/octet-stream

我想确定行之间的行数,它们在字符串“Iteration 1”和“Iteration 2”中完全结束,并将行数存储到变量abc abc, Iteration 1 abc abc, Iteration 2 ... abc abc, Iteration 19 abc abc, Iteration 20 。在上面的示例中,numlines应包含值1。

我想使用numlineswc -lsed

3 个答案:

答案 0 :(得分:4)

Vijay's helpful sed answer简洁,但总是处理整个输入文件(并且还会创建额外的子进程,因为必须调用wc -l好吧 - 尽管总的来说这并不重要。)

尝试以下 awk解决方案在找到范围结束时立即退出(它也只创建一个子进程 - subshel​​l被优化而不是简单的awk命令);对于大输入文件,这可能很重要,具体取决于文件在文件内的位置:

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

karakfa提供帮助优化命令的提示。

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

答案 1 :(得分:3)

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

答案 2 :(得分:1)

到目前为止,所有解决方案都使用regexp而不是字符串,因此当字符串包含RE元字符时会失败。这就是如你在问题中所要求的那样用字符串做的事情:

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