用正则表达式置换矩阵的参数

时间:2013-03-12 12:56:32

标签: python regex perl sed

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

祝福

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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)'

获得参数列表后,只需将字符串重新组合在一起就可以置换它们