Substituindo parênteses por colchetes em expressões matemáticas, usando backreferences em sed

0

É possível, em sed , referenciar novamente uma ocorrência ou um padrão com o mesmo número de vezes que ela foi referenciada?

Exemplo: para uma determinada entrada,

((23 + 5)(23 + 5))
11 x (2+1) = 11 x 3 = 33
3x(5+2)

Eu preciso substituir todas as ocorrências de ( com [ e ) com ] usando sed apenas referência (resolvi isso com tr e sed ). Além disso, o número de colchetes pode variar.

    
por abhishek nair 04.10.2018 / 23:50

1 resposta

7

Se você quiser simplesmente substituir todos os ( por [ e ) por ] , não haverá necessidade de referências anteriores. Um simples tr fará o trabalho:

$ tr '()' '[]' <file
[[23 + 5][23 + 5]]
11 x [2+1] = 11 x 3 = 33
3x[5+2]

ou, com sed ,

$ sed 'y/()/[]/' <file
[[23 + 5][23 + 5]]
11 x [2+1] = 11 x 3 = 33
3x[5+2]

Uma backreference só pode substituir algo existente na entrada por si mesma, por isso estou assumindo que você está pensando em tentar combinar as coisas entre os parênteses e depois substituí-las pelas mesmas coisas, mas entre colchetes. Você pode fazer isso com um loop:

$ sed -E -e ':loop' -e 's/\(([^()]+)\)/[]/; tloop' <file
[[23 + 5][23 + 5]]
11 x [2+1] = 11 x 3 = 33
3x[5+2]

Aqui, primeiro definimos um rótulo, loop , e depois fazemos a nossa substituição. Se a substituição fez algo, então voltamos ao rótulo loop . Precisamos fazer isso porque usar s/.../.../g não encontrará correspondências sobrepostas e haverá sobreposição de correspondências assim que houver parênteses aninhados.

A substituição s/\(([^()]+)\)/[]/ encontrará qualquer string não vazia entre parênteses, que não contenha ( ou ) e substitua isso por si mesma, mas com os parênteses circundantes substituídos por colchetes.

Para a linha de entrada

((23 + 5)(23 + 5))

isso fará com que sed execute a substituição quatro vezes:

  1. ([23 + 5](23 + 5)) , o primeiro parêntese interno é substituído.
  2. ([23 + 5][23 + 5]) , depois o segundo interno.
  3. [[23 + 5][23 + 5]] , depois o exterior.
  4. A última substituição não fará nada e o loop sairá.

Usar o sinalizador g no final da expressão de substituição fará com que as duas primeiras etapas acima sejam executadas na mesma substituição, pois elas não são sobrepostas.

Com expressões regulares básicas equivalentes (o acima usa uma expressão regular estendida para legibilidade):

sed -e ':loop' -e 's/(\([^()][^()]*\))/[]/; tloop' <file
    
por 05.10.2018 / 07:49