为了提高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做这个吗?
祝福
答案 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)'
获得参数列表后,只需将字符串重新组合在一起就可以置换它们