在模式之前提取数字

时间:2015-01-29 09:59:16

标签: regex bash awk sed grep

我有一个包含类似这样的序列的文件(如果你想知道,国际象棋符号中使用的PGN文件):

1. e4 e5 2. Nf3 Nf6 3. Nc3 d6 4. d4 a6 5. Bc4 Be6 6. Bxe6 fxe6 7. Be3 Nc6 8. a3 h6 9. Qd3 Qd7 10. b4 b6 11. d5 exd5 12. Nxd5 Ne7 13. c4 Nexd5 14. exd5 e4 15. Qe2 exf3 16. Qxf3 O-O-O 17. O-O Re8 18. h3 Kb8 19. a4 Be7 20. b5 a5 21. Bd4 Ref8 22. Rfe1 Ne8 23. Qe3 Rf7 24. Qe6 Bd8 25. Re3 Re7 26.
Qxd7 Rxd7 27. Rae1 Nf6 28. g4 g5 29. Re6 Rf7 30. Kg2 h5 31. f3

请注意,它分为几行。现在,从这个不断更新的文件中,我想在最后一个点之前提取数字,在本例中为31

我设法仅提取最后一行并删除可能的空行:

sed '/^ *$/d' thefile.pgn | tail -1

但是,我不知道如何捕获点之前的最后一个数字。是否有可以完成这项工作的工具(awk,sed,grep,whathaveyou)?

4 个答案:

答案 0 :(得分:2)

这个awk也可以工作:

awk -F '\.' 'END{split($(NF-1), a, " "); print a[length(a)]}' file
31

答案 1 :(得分:1)

如果文件只包含一行,则可以使用sed

$ sed -r 's/.* ([0-9]+)\. \w+$/\1/' file
31

这匹配所有行并捕获行尾之前的最后一个数字块。然后,它使用\1打印回来。

如果文件包含多行,请转到grep

grep -Po " \K[0-9]+(?=\.)" file

有了这个,您可以获得不同行中的所有数字。要获取最后一行,只需输入tail -1

$ grep -Po " \K[0-9]+(?=\.)" file | tail -1
31

它的工作原理是匹配点之前出现的所有数字。当我们使用-o时,每个匹配都打印在不同的行中,因此使用tail -1来获取最后一个匹配。

答案 2 :(得分:0)

您的sed脚本可以轻松扩展,以执行tailgrep部分。 (使用sed -n和正则表达式来控制打印,甚至不再需要删除空行。)

sed -n '$s/^.* \([1-9][0-9]*\)\.[^.]*$/\1/p' thefile.pgn

这假设最后一行永远不会为空。也不难适应这个额外的要求。这是一个适度更复杂的版本:

sed -n '/^.* \([1-9][0-9]*\)\.[^.]*$/{;s//\1/;x;};$!b;x;p' thefile.pgn

与模式匹配的行减少到最后一个数字并存储。在最后一行,检索存储的字符串并打印出来。

答案 3 :(得分:0)

谢谢大家!很难在答案之间做出选择。这是我的版本:

sed -e 's/\*//' -e '/^ *$/d' thefile.p | tail -1 | awk '{print $(NF-1)}' FS='[ .]+'

我接受fedorqui的回答,因为它更优雅。