【问题标题】:permute arguments of matrix with regex用正则表达式置换矩阵的参数
【发布时间】:2013-02-28 00:05:30
【问题描述】:

为了提高 FORTRAN 代码的性能,我想置换数组的索引,以便将第 4 个索引移动到第二位,例如,我想更改以下行

ts(l,i,j,k) = ts(l,i,j,k1(i,j))

ts(l,k,i,j) = ts(l,k1(i,j),i,j)

请注意,这只是一个示例行,索引并不总是称为 i,j,k,l... 我只知道数组的名称和等级。所以我不能只用逗号分隔 4 个参数,因为一个参数也可以是一个带有逗号的矩阵(在上述情况下为 k1(i,j))。所以我的第一个想法

sed -r  's/ts\(([^,]+),([^,]+),([^)]+),([^,]+)\)/ts\(\1,\4,\2,\3\)/g' *.F

在这种情况下失败(上面代码行中的 rhs),因为它给出了:

ts(l,k,i,j) = ts(l,j),i,j,k1(i)

我需要的是一个正则表达式,它仅在打开最多 1 个括号时才拆分我的数组索引。有人可以给我一个提示如何使用 sed/python/perl 做到这一点吗?

祝你好运

【问题讨论】:

  • 你确定括号永远不会嵌套得比这更深吗?
  • 您确定这会提高您的表现吗?如果您的循环以正确的顺序编写,我预计性能会因此下降。 (当然,只要您将旧版本签入您的 VCS,就可以进行实验并查看)
  • 现在,fortran 并不是全部大写 :)
  • @Tim 是的,我认为它不会更深入......如果有 1-2 个例外,我会很乐意手动修复这些行。
  • @mgilson 不是我不确定,但如果有帮助我想试试。

标签: python regex perl sed


【解决方案1】:

如果括号没有比您的示例更深地嵌套,这应该可以工作:

sed -r  's/ts\(((\([^()]*\)|[^(),])*),((\([^()]*\)|[^(),])*),((\([^()]*\)|[^(),])*),((\([^()]*\)|[^(),])*)\)/ts(\1,\7,\3,\5)/g' *.F

不是很漂亮……

说明:

(        # Match and capture...
 (       # either
  \(     #  an opening parenthesis
  [^()]* #  any number of non-parenthesis characters
  \)     #  a closing parenthesis
 |       # or  
  [^(),] #  a character besides parentheses or comma
 )*      # any number of times
)        # End of capturing group

【讨论】:

  • 我明白了:sed: -e expression #1, char 126: Invalid before regular expression
  • 嗯,我不使用sed,所以我只是从问题中复制了你的示例,只交换了正则表达式。由于我没有使用与您不同的正则表达式功能,因此我不知道可能是什么问题。也许我在粘贴时犯了一个错误......
  • @RaphaelRoth:啊,你的正则表达式中有一个未转义的右括号。现在可以用了吗?
  • 不,不幸的是它无法正常工作...目前无法找出问题所在
  • 只是为了确保:您的正则表达式确实有效,只是产生了不正确的结果,对吧?
【解决方案2】:

也许直接的正则表达式有点困难。如果您有可用的脚本语言,请尝试以下操作。在您检测到包含数组访问的行之后。 (在python中)

import re
def getArguments(rhs):
    """
        Separates string on commas that are in the first level parentheses
    """
    lvl = 0
    argSplits = []
    for i, c in enumerate(rhs):
        if c == '(':
            lvl += 1
            if lvl == 1:
                argSplits.append(i)
        elif c == ')':
            lvl -= 1
            if lvl == 0:
                argSplits.append(i)
                break
        if lvl < 0:
            raise ValueError('Parentheses do not match')
        if lvl == 1:
            if c == ',':
                argSplits.append(i)
    args = []
    for i in range(len(argSplits)-1):
        args.append(rhs[argSplits[i]+1:argSplits[i+1]])
    return args

line = r'ts(l,i,j,k) = ts(l,i,j,k1(i,j))'
# get righthand side of equ
rhs = re.split('=', line)[1]   
# get arguments
args = getArguments(rhs)
# args = ['l', 'i', 'j', 'k1(i,j)']

# try: line = r'ts(l,i,j,k) = ts(l,i,j,k1(i(am(crazy(!))i),j))'
# you get: getArguments(rhs) --> ['l', 'i', 'j', 'k1(i(am(crazy(!))i),j)'

一旦你有了参数列表,你就可以在将字符串重新组合在一起时对它们进行置换

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多