【问题标题】:Extracting minimum and maximum from line number grep从行号 grep 中提取最小值和最大值
【发布时间】:2013-04-09 09:33:33
【问题描述】:

目前,我在 bash 脚本中有一个命令,该命令对文本文件中的给定字符串进行 greps 并仅使用 sed 打印行号 ...

grep -n "<string>" file.txt | sed -n 's/^\([0-9]*\).*/\1/p'

grep 可以找到多个匹配项,因此打印多个行号。从这个命令的输出中,我想提取最小值和最大值,并将它们分配给各自的 bash 变量。我怎样才能最好地修改我现有的命令或添加新命令来完成这个?如果需要使用 awk 或 sed,我倾向于使用 sed。谢谢!

【问题讨论】:

    标签: bash


    【解决方案1】:

    你可以用这个得到最小值和最大值:

    grep -n "<string>" input | sed -n -e 's/^\([0-9]*\).*/\1/' -e '1p;$p'
    

    您也可以将它们读入数组:

    F=($(grep -n "<string>" input | sed -n -e 's/^\([0-9]*\).*/\1/' -e '1p;$p'))
    echo ${F[0]} # min
    echo ${F[1]} # max
    

    【讨论】:

    • Grep 从sed -n g/re/p 得到它的名字。您应该能够将所有内容组合到 sed 中,而不是将 grep 的输出通过管道传输到 sed 中。
    • 但是行号的事情使这变得复杂了。看起来你需要一个 sed-sed 管道来做到这一点。
    【解决方案2】:
    grep -n "<string>" file.txt | sed -n -e '1s/^\([0-9]*\).*/\1/p' -e '$s/^\([0-9]*\).*/\1/p'
    

    【讨论】:

    • 谢谢!你的答案有效。理想情况下,我想只打印最小值或最大值。有没有办法让您的命令只打印最小值或最大值?或者您会建议 perreal 在下面提供的相同解决方案吗?
    【解决方案3】:
    grep .... |awk -F: '!f{print $1;f=1} END{print $1}'
    

    【讨论】:

    • 这可能更容易理解:... | awk -F: 'NR==1{print $1} END{print $1}'
    • @AnsgarWiechers 哈哈,是的!我只是想到了布尔值......“忘记”NR 是行号。 :)
    • 也不需要grep!在 awk 中构建了 grep。为雨林保存一个过程! ;)
    • @TrueY 不是 100% 正确的。你怎么知道 OP 没有写 Perl 正则表达式?
    • @Kent:请参阅下面的示例。如果使用awk,则不需要grep(或sed,或wc 或类似...)。但是,你当然是对的! Grepsed 使用旧版本的正则表达式,所以如果您绑定到 RE 并且您无法转换为 ERE,那么您必须使用它们。但这非常罕见……
    【解决方案4】:

    这就是我的做法,因为grep -n 'pattern' fileline number:line contents 格式打印输出...

        minval=$(grep -n '<string>' input | cut -d':' -f1 | sort -n | head -1)
        maxval=$(grep -n '<string>' input | cut -d':' -f1 | sort -n | tail -1)
    

    cut -d':' -f1 命令在冒号周围拆分grep 输出并仅取出第一个字段(行号),sort -n 按升序对数字行号进行排序(它们已经在其中,但是确保它是一个很好的做法),然后head -1tail -1 分别删除排序列表中的第一个和最后一个值,即最小值和最大值,并将它们分别分配给变量$minval$maxval

    希望这会有所帮助!

    编辑:事实证明你不能按照我最初的方式做,因为回显一个换行符分隔值的列表显然会将它们连接成一行。

    【讨论】:

    • 我喜欢这个解决方案,但它似乎给了我一个错误:head: cannot open '96' for reading: No such file or directory head: cannot open '100' for reading: No such file or directory。当然,这些数字是在我的输入文件的上下文中,但它似乎不喜欢headtail。有什么建议吗?
    • 这也是tail: option used in invalid context -- 1
    • 原来你不能按照我最初的方式去做(使用第三个变量),因为当你回显时,它会将所有值放在一行上(这意味着头和尾不好好工作)。上面的代码现在应该可以正常工作了
    【解决方案5】:

    这可以通过一个过程来完成。像这样:

    awk '/expression/{if(!n)print NR;n=NR} END {print n}' file.txt
    

    然后您可以分配给一个数组(按照 perreal 的建议)。或者您可以修改此脚本并使用 eval 分配给变量

    eval $(awk '/expression/{if(!n)print "A="NR;n=NR} END {print "B="n}' file.txt)
    echo $A
    echo $B
    

    输出(file.txt 包含三行 expression

    1
    3
    

    【讨论】:

      猜你喜欢
      • 2019-11-22
      • 2021-06-20
      • 1970-01-01
      • 2014-10-17
      • 1970-01-01
      • 2021-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多