【问题标题】:How to determine number of lines between two strings using Bash and standard utilities?如何使用 Bash 和标准实用程序确定两个字符串之间的行数?
【发布时间】:2016-10-12 01:59:20
【问题描述】:

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

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

【问题讨论】:

标签: linux bash awk sed wc


【解决方案1】:

Vijay's helpful sed answer 很简洁,但总是处理整个输入文件(并且还会创建额外的子进程,因为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 ($)。
手头的字符串恰好不包含需要转义的正则表达式元字符(使用\),但在其他情况下您可能必须这样做。
如果要匹配的字符串不是预先知道的文字,那么通用转义将很困难;在这种情况下,考虑Ed Morton's solution,它基于字符串,而不是正则表达式。

【讨论】:

  • 为什么不/Iteration 1$/{b=NR} /Iteration 2$/{print NR-b-1; exit}
  • @EdMorton:是的,命令中使用的正则表达式与end exactly in the strings "Iteration 1" and "Iteration 2" 的行匹配,按要求。
  • @EdMorton:是的。在我添加的脚注和指向您答案的指针之间,我认为我们已经涵盖了所有内容。
【解决方案2】:
sed '/Iteration\ 1/,/Iteration\ 2/!d;//d' filename  | wc -l

【讨论】:

  • 比我的简洁多了:)
  • 当文件包含“Iteration 10”和“Iteration 20”等时,这似乎会中断。
  • @mklement0 我已经更新了我的问题中的示例文件,以反映解决方案应处理的数据的性质。
  • 聪明简洁的解决方案;请考虑添加解释。唯一的缺点是整个输入文件总是被处理。
  • 会像@IslandPatrol 提到的那样失败,在其他情况下,你为什么要逃避空间?空格不是正则表达式元字符。
【解决方案3】:

到目前为止,所有解决方案都使用正则表达式,而不是字符串,因此当您的字符串包含 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

【讨论】:

  • 虽然我不认为传递任意字符串以匹配是在问题的范围内(尽管有随意的措辞),但 ++ 是一个更通用的解决方案。为了优化,请考虑将next 附加到第一个操作,将exit 附加到第二个操作。
  • 另外,为了更好地说明您的方法的优势,我建议展示如何通过外部变量传递字符串awk -v begStr='Iteration 1' -v endStr='Iteration 2' '...'
  • 我没有这样做,因为如果 OP 需要这样的解决方案,我必须解释/处理反斜杠扩展和 idk。我也不想浪费时间优化它,因为 OP 可能无论如何都不会使用它,只是觉得这对于将来遇到这个问题的任何人都很重要,所以看看如何真正使用字符串而不是正则表达式。
猜你喜欢
  • 1970-01-01
  • 2020-10-15
  • 1970-01-01
  • 2017-04-23
  • 2022-11-02
  • 1970-01-01
  • 2020-04-27
  • 2012-07-07
  • 1970-01-01
相关资源
最近更新 更多