定位字符串中的特定事件并替换它

时间:2015-07-20 21:08:31

标签: replace lua

我有一个包含多个/的字符串,我正在尝试将此字符串转换为LaTeX代码。基本上(a)/(b)变为\\dfrac{a}{b}

难点在于(a)和/或(b)可能包含其他/

为了尊重括号平衡,我想从左到右替换/,并相应地将它们替换为它周围的内容。我试了一下,但我不知道如何定位特定的/并替换。使用位置和长度参数似乎非常复杂。

function ToFrac (s)
    while s:find ("/") ~= nil
    do

    -- Replace : \dfrac{}{}/() -> \dfrac{\dfrac...}{}
    if ( s:find ( '\\dfrac%b{}%b{}/%b()' , j ) ~= nil )
    then
    x,y,num,den = s:find( '(\\dfrac%b{}%b{})/(%b())' )
    den = den:gsub( '.(.+).' , '%1' )
    s = s:gsub( '(\\dfrac%b{}%b{})/(%b())',
                            "\\dfrac{"..num.."}{"..den.."}" , 1 )
    end

    print ('### -- ', s)

    -- Replace : ()/\dfrac{}{} -> \dfrac[}]{\dfrac...}
    if ( s:find ( '(%b()/\\dfrac%b{}%b{}' ) ~= nil )
    then
    x,y,num,den = s:find( '((%b())/(\\dfrac%b{}%b{})' )
    num = num:gsub( '.(.+).' , '%1' )
    s = s:gsub( '((%b())/()\\dfrac%b{}%b{})',
                            "\\dfrac{"..num.."}{"..den.."}" , 1 )
    end

    print ('### -- ', s)

    -- Replace : ()/() -> \dfrac{}{}
    if ( s:find ( '%b()/%b()' , 1 ) ~= nil )
    then
        x,y,num,den = s:find( '(%b())/(%b())' )
        num = num:gsub( '.(.+).' , '%1' )
        den = den:gsub( '.(.+).' , '%1' )
        s = s:gsub( '(%b())/(%b())',
                        "\\dfrac{"..num.."}{"..den.."}" , 1 )
        Done = true
    end

    print ('### -- ', s)

    end -- while

    return (s)

end

s = "((a)/(b))/(c)"
print (s, ToFrac(s))

s = "(a)/((b)/(c))"
print (s, ToFrac(s))

s = "(a)/(b)/(c)/(d))"
print (s, ToFrac(s))

s = "((a)/(b))/((c)/(d))"
print (s, ToFrac(s))

2 个答案:

答案 0 :(得分:3)

'替换' string.gsub的参数可以是一个函数。 使用该函数,您可以递归地将替换应用于分子和分母,并以此方式构建结果。 string.sub可用于从分子和分母中删除括号。

function to_frac(expr)
     return (expr:gsub('%s*(%b())%s*/%s*(%b())%s*',
         function(num, denom)
             return '\\dfrac{'..to_frac(num:sub(2,-2))..'}{'
                              ..to_frac(denom:sub(2,-2))..'}'
         end))
end


expr = ' (a )/((b) / (c))' -- \dfrac{a }{\dfrac{b}{c}}

print(to_frac(expr))


expr = '((a)/((b)/(c)))/(e)' -->\dfrac{\dfrac{a}{\dfrac{b}{c}}}{e}
print(to_frac(expr))

如果您想超越使用括号来分隔参数并遵守优先规则,那么请查看LPeg。

答案 1 :(得分:3)

rpattiso的想法的修订版本:

function to_frac(expr)
  local t
  return expr == '' and '' or (expr..'()'):gsub('(.-)(%b())',
    function(prefix, subexpr)
      local replace_with = ''
      if not prefix:find'^%s*/%s*$' then
        t, replace_with = {}, (not t and ''
          or t[2] and '\\dfrac{'..t[1]..'}{'..t[2]..'}'
          or '('..t[1]..')')..prefix
      elseif t[2] then
        t = {'\\dfrac{'..t[1]..'}{'..t[2]..'}'}
      end
      table.insert(t, to_frac(subexpr:sub(2,-2)))
      return replace_with
    end
  )
end

print(to_frac' (a )/((b) / (c))')   --> \dfrac{a }{\dfrac{b}{c}}
print(to_frac'((a)/((b)/(c)))/(e)') --> \dfrac{\dfrac{a}{\dfrac{b}{c}}}{e}
print(to_frac'(a)/(b)/(c)/(d)')     --> \dfrac{\dfrac{\dfrac{a}{b}}{c}}{d}