4

为了提高 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 做到这一点吗?

最良好的祝愿

4

2 回答 2

2

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

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
于 2013-03-12T13:07:23.543 回答
2

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

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)'

获得参数列表后,您可以在将字符串重新组合在一起时对它们进行置换

于 2013-03-12T14:53:47.933 回答