【问题标题】:Regular expression to reformat blocks of integers (magic squares)正则表达式重新格式化整数块(魔方)
【发布时间】:2015-07-25 21:05:36
【问题描述】:

正则表达式要求

我有一个包含幻方的大文件,以空格分隔的四个一组:

 2 16  1 15    10  5 12  7     9  3 14  8    13  6 11  4
14  9  8  3     3  9  8 14     5 10  7 12    12 10  7  5
11  4 13  6     6  4 13 11    16 15  2  1     1 15  2 16
 7  5 12 10    15 16  1  2     4  6 11 13     8  3 14  9

最终我想找到并重新格式化这些组,这样每个单独的幻方就会像这样单独显示:

 2 16  1 15
14  9  8  3
11  4 13  6
 7  5 12 10

10  5 12  7
 3  9  8 14
 6  4 13 11
15 16  1  2

 9  3 14  8
 5 10  7 12
16 15  2  1
 4  6 11 13

13  6 11  4
12 10  7  5
 1 15  2 16
 8  3 14  9

查找每组四位数

首先,我有一个正则表达式,它可以找到所有四个数字的组,但这只会给我需要的 16 个匹配项如果我指定每个整数前面有 0-2 个空格:

(( {0,2}\d{1,2}){4}).*?

(saved version on Regexr)

解决的问题

我只想捕获每列开头的整数前面的零个或一个空格,但不是分隔每个 16 块的四个空格。

更大的问题

然后我需要捕获 16 个四个整数组中的每一个,并将它们重新格式化为捕获的组

\1\5\9\13\n\n

给予:

 2 16  1 15
14  9  8  3
11  4 13  6
 7  5 12 10

但到目前为止,我的正则表达式捕获了所有内容。如何分离捕获组以实现此目的?

【问题讨论】:

  • 说实话,我认为正则表达式不是解决这个问题的正确方法。正则表达式用于匹配和搜索,转换输入,这显然是一个例子。即使是一个简单的 shell 脚本也可以比正则表达式做得更好/更快。
  • 我确实想到了 awk 或 sed。自从我使用 awk 以来已经有几年了,但它在我上次使用它时在一个巨大的(数千个文件)网站中转换了一个字符串。所以你可能是对的。

标签: regex


【解决方案1】:

使用像 python 这样的脚本语言

这是我的解决方案。我认为效果很好。

squares = []
row_counter = 0
four = None
with open('magic-squares.txt') as f:
    for row in f:
        numbers = row.split()
        if numbers:
            if row_counter == 0:
                if four:
                    squares += four
                four = [[],[],[],[]]
            for i in range(4):
                four[i] += numbers[i*4:i*4+4]
            row_counter += 1
            row_counter %= 4

with open('output.txt', 'w') as f:
    f.write('\n'.join(' '.join(square) for square in squares))

with open('output2.txt', 'w') as f:
    f.write(
        '\n\n'.join(
            '\n'.join(
                ''.join(
                    ["{:<2} ".format(item) for item in square[i*4:(i+1)*4]]
                ) for i in range(4)
            ) for square in squares
        )
    )

【讨论】:

  • 谢谢 Graeme - 我今晚会试试这个。
  • 终于开始运行它并且运行良好。只需添加最后四行的副本即可提取最后四个方块。
【解决方案2】:

我可以建议你这样做:

(( {0,2}?\d{1,2}){4}) +(( {0,2}?\d{1,2}){4}) +(( {0,2}?\d{1,2}){4}) +(( {0,2}?\d{1,2}){4})

你可以得到这样的结果:

$1

 2 16  1 15
14  9  8  3
11  4 13  6
 7  5 12 10

$3

10  5 12  7
3  9  8 14
6  4 13 11
15 16  1  2

$5
...

$7
...

【讨论】:

  • 谢谢,但是 - 就像我最初的尝试一样 - 这会每隔一个找到一个整数,所以我不能使用它。
【解决方案3】:

似乎正则表达式不是该工作的好选择,但它是可能的。例如,要一次匹配所有四个正方形,并按您想要的顺序提取它们,您可以使用这个长得可笑的正则表达式:

^((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)\s+(.+)\n((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)\s+(.+)\n((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)\s+(.+)\n\s+((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)\s+((?:\s{0,2}\d+)+)

DEMO

然后使用从 $1 到 $16 的所有组来获得正方形。但是我不确定它在正则表达式练习之外是否有用。

【讨论】:

  • 这个长得可笑的正则表达式实际上在我的文本编辑器中眨眼间就完成了这项工作。也感谢您的演示。
猜你喜欢
  • 1970-01-01
  • 2010-12-13
  • 2011-01-09
  • 2023-02-04
  • 1970-01-01
  • 1970-01-01
  • 2016-10-07
  • 2013-04-28
  • 2021-01-16
相关资源
最近更新 更多