如何grep最后一次出现的线条图案

时间:2014-06-03 11:37:41

标签: bash shell awk sed grep

我有一个包含内容的文件

x
a
x
b
x
c

我想grep最后一次出现,

x
c

当我尝试

sed -n  "/x/,/b/p" file

它会列出所有行,从x开始到c

6 个答案:

答案 0 :(得分:25)

我不确定我的问题是否正确,所以这里有一些黑暗的镜头:

  • 打印x的最后一次出现:

    grep x file | tail -1
    
  • 从第一个匹配行打印文件到结束:

    awk "/x/ { flag = 1 }; flag" file
    
  • 从最后一个匹配行打印文件到结尾(如果不匹配则打印所有行):

    tac file | awk "!flag; /x/ { flag = 1 }; " | tac
    

答案 1 :(得分:3)

这可能适合你(GNU sed):

sed '/x/h;//!H;$!d;x' file

保存最后x以及保留空间中的内容,并将其打印在文件末尾。

答案 2 :(得分:1)

不确定如何使用sed执行此操作,但您可以尝试awk

awk '{a=a"\n"$0; if ($0 == "x"){ a=$0}}  END{print a}' file

答案 3 :(得分:1)

grep -A 1 x file | tail -n 2

-A 1告诉grep在匹配行之后打印一行
使用tail,您将获得最后两行。

或以相反的方式:

tac fail | grep -B 1 x -m1 | tac

注意:您应确保模式足够“强”,以使其正确。即以^开头并以$结尾。

答案 4 :(得分:0)

POSIX vi(或 ex 或 ed),以防对某人有用

当然是在命令模式下完成

:set wrapscan

转到第一行,然后向后搜索! 1G?pattern

较慢的方式没有 :set wrapscan

G$?pattern

说明:

G 转到最后一行

移到该行的末尾$

? 向后搜索 pattern

第一个向后匹配将与最后一个向前匹配相同

无论哪种方式,您现在都可以删除当前(匹配)之上的所有行

:1,.-1d

kd1G

如果同一行上有多个匹配项,您也可以使用 d0 在行删除之前删除到匹配行的开头。

POSIX awk,如在 get last line from grep search on multiple files

awk '(FNR==1)&&s{print s; s=""}/PATTERN/{s=$0}END{if(s) print s}'

答案 5 :(得分:0)

如果你想以真正可怕的单行方式执行 awk,但让 awk 更接近函数式编程范式语法,而不必跟踪最后一次出现的时间

mawk/mawk2/gawk 'BEGIN { FS = "=7713[0-9]+="; RS = "^$";

 } END { print ar0[split($(0 * sub(/\n.+$/,"",$NF)), ar0, ORS)] }'

这里我使用了多个 awk 简写:

    sub(/[\n.+$/, "", $NF) # trimming all extra rows after pattern

g/sub() 返回进行的替换次数,因此将其乘以 0 会强制 split() 拆分 $0,而不是整个文件。

split() 返回数组中的项数(这是最后一个元素位置的另一种说法),所以即使我已经修剪掉了尾随的 \n,我仍然可以直接打印 ar0[split()],知道 ORS 将填充缺少的尾随 \n

这就是为什么这段代码看起来像我试图在定义数组本身之前提取数组项,但由于所需的逻辑流,数组在它到达时被定义<强>打印。

现在如果你想要更简单的东西,这两个也行

mawk/gawk 'BEGIN { FS="=7713[0-9]+="; RS = "^$" 

   } END { $NF = substr($NF, 1, index($NF, ORS)); 
           
           FS = ORS; $0 = $0; print $(NF-1) }'

mawk/gawk '/=7713[0-9]+=/ { lst = $0 } END { print lst }'
  • 我没有使用与 OP 相同的 x|c 要求来展示这些工作,无论您是需要固定字符串还是基于正则表达式的匹配。