Python 带正则表达式矩阵的置换变元

Python 带正则表达式矩阵的置换变元,python,regex,perl,sed,Python,Regex,Perl,Sed,为了提高FORTRAN代码的性能,我想排列数组的索引,以便将第四个索引移到第二位,例如,我想更改以下行 ts(l,i,j,k) = ts(l,i,j,k1(i,j)) 到 请注意,这只是一个示例行,索引并不总是称为i,j,k,l。。。我只知道数组的名称和秩。所以我不能在逗号处分开4个参数,因为一个参数也可以是一个有逗号的矩阵(在上面的例子中是k1(I,j))。所以我的第一个想法 sed -r 's/ts\(([^,]+),([^,]+),([^)]+),([^,]+)\)/ts\(\1,\4

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

ts(l,i,j,k) = ts(l,i,j,k1(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实现这一点吗


最好的祝愿

如果括号的嵌套深度不超过您的示例中的嵌套深度,则此操作应该有效:

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

也许直接regexp有点困难。如果有可用的脚本语言,请尝试以下操作。检测到包含阵列访问的行之后。 (python语言)

重新导入
def getArguments(rhs):
"""
用第一级括号中的逗号分隔字符串
"""
lvl=0
argSplits=[]
对于枚举中的i,c(rhs):
如果c=='(':
lvl+=1
如果lvl==1:
argSplits.append(i)
elif c==')':
lvl-=1
如果lvl==0:
argSplits.append(i)
打破
如果lvl<0:
raise VALUERROR('括号不匹配')
如果lvl==1:
如果c==',':
argSplits.append(i)
args=[]
对于范围内的i(len(argSplits)-1):
args.append(rhs[argSplits[i]+1:argSplits[i+1]]
返回参数
直线=r'ts(l,i,j,k)=ts(l,i,j,k1(i,j))'
#得到equ的右侧
rhs=重新拆分('=',行)[1]
#获取参数
args=getArguments(rhs)
#args=['l','i','j','k1(i,j)']
#try:line=r'ts(l,i,j,k)=ts(l,i,j,k1(i(疯狂(!)i),j))'
#你会得到:getArguments(rhs)->['l','i','j','k1(i(am(疯狂(!)i),j)'

一旦有了参数列表,就可以在重新组合字符串时对其进行排列了

是否确定圆括号的嵌套深度永远不会超过该值?是否确定这将提高性能?如果循环的编写顺序正确,我预计性能会因此降低。(当然,如果你把旧版本签入你的VCS中,实验和查看也没有什么坏处)而且现在,
fortran
并不是用大写字母拼写的:)@蒂姆:是的,我认为它不会更深入……如果有1-2个异常,我很乐意手动修复这些行。@mgilson不确定,但如果有帮助,我想尝试一下。我得到:sed:-e expression#1,char 126:无效的前向正则表达式hm,我不使用
sed
,所以我只是从问题中复制了你的示例,仅交换了正则表达式。由于我没有使用任何与您不同的正则表达式功能,我不知道可能有什么问题。也许我粘贴时出错了…@RaphaelRoth:啊,您的正则表达式中有一个未替换的右括号。它现在能用了吗?不,不幸的是它不起作用…无法找出问题所在,只是为了确保:你的正则表达式确实有效,只是产生了一个不正确的结果,对吗?
(        # 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
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)'