打印最后一个分隔符之后的所有数据

打印最后一个分隔符之后的所有数据

如何打印文件中最后一个分隔符之后的所有数据?文件数据如下:

data1
data2
######################
data3
data4
######################
data5
data6

我想打印:

data5
data6

因为 ###################### 是分隔符。

*行数未知。

我试过:

$ cat file | awk -F "#"  '{print $NF}'

但输出是:

data1
data2
data3
data4
data5
data6

答案1

使用awkwith tac(有些系统也有tail -r这样的功能):

$ tac file | awk '/^#+$/{exit} 1' | tac
data5
data6

tac或者如果您还没有tac/ ,则编写您自己的类似函数tail -r(这里假设 acat支持非标准-n选项,如果您没有,则使用awk -v OFS='\t' '{print NR, $0}'而不是cat -n):

$ mytac() { cat -n -- "$@" | sort -rn | cut -f2-; }
$ mytac file | awk '/^#+$/{exit} 1' | mytac
data5
data6

awk或者如果您没有tac并且不想编写自己的,则单独使用任何一个:

$ awk '{rec=rec $0 ORS} /^#+$/{rec=""} END{printf "%s", rec}' file
data5
data6

或者,如果您的文件足够小,可以一次将所有内容读入内存,则使用 GNUawk进行多字符:RS

$ awk -v RS='^$' -v ORS= -F'(^|\n)#+(\n|$)' '{print $NF}' file
data5
data6

或者再次使用 GNU awk 进行多字符 RS 并保留 END 部分最后 $0 的值:

$ awk -v RS='(^|\n)#+(\n|$)' -v ORS= 'END{print}' file
data5
data6

无论输入是存储在文件中还是来自管道,上述所有内容都将起作用,因为它只读取输入一次。如果它存储在文件中(因此可以读取两次),您可以使用各种工具组合获得许多其他选项,例如:

$ tail -n +"$(awk '/^#+$/{n=NR} END{print n+1}' file)" file
data5
data6

1 但请注意,对于不可查找的文件(例如管道),输入需要通过tac/ tail -r/临时存储sort在内存中或可能在临时文件中。在某些系统上,tail -r它愿意存储的数量(在内存中)的限制相对较低。

答案2

使用 GNU awk

awk 'BEGIN{FS="######################\n"; RS=""} {print $NF}' file

输出:

数据5
数据6

$NF包含最后一列。

看:8 个强大的 awk 内置变量 – FS、OFS、RS、ORS、NR、NF、FILENAME、FNR

答案3

这是一个奇特的单线:

tail -n+$(( $(grep -nF '######################' test.txt | tail -1 | cut -d: -f1) + 1)) test.txt

以及更合理的单独解释

last_delimiter_line=$(grep -nF '######################' test.txt | tail -1 | cut -d: -f1)
data_line_num=$((last_delimiter_line + 1))
tail -n+$data_line_num test.txt
  • 搜索grep文件中的所有分隔符并打印每个匹配项及其找到的行号。
  • 删除tail除最后一场比赛之外的所有比赛
  • 提取cut找到的最后一个分隔符的行号,该行号存储在last_delimiter_line
  • 要打印的第一行在后面last_delimiter_line并存储在data_line_num
  • 最后一个tail命令从 test.txt 行开始打印任何内容data_line_num

相关内容