Можно ли найти и заменить строку, содержащую один символ, используя команды оболочки? - PullRequest
0 голосов
/ 25 ноября 2018

Можно ли с помощью sed или awk или любых других команд оболочки распознать строки с одним символом, например ), а затем заменить их чем-то другим?Может быть много строк, содержащих ), но он заменяет только строки, в которых есть один символ ).Пример:

exp =  ... +
     (    x  
        + 2*(y) 
        + z
      )
       + ...

Я пытаюсь получить следующее:

exp =  ... +
     (    x 
        + 2*(y) 
        + z
      }
       + ...

Если я заменю ) обычной командой sed, она заменит все совпадения на ).

sed -i -e 's/)/\}/g' file

даст

exp =  ... +
     (    x
        + 2*(y} 
        + z
      }
       + ...

Есть ли выход?

РЕДАКТИРОВАТЬ: пример с вложенными скобками, где одна строка содержит внутреннюю вложенную скобку,решение не работает (для этого примера):

sed -e 's/(\(.*\))/{\1}/g'

      ...
   + LNb * (
      + ( - 224/27 + ( - 8/3)*Lqf^2 + (80/9)*Lqf)*CF*NF
      + (1616/27 - 56*[Zeta[3]] + ( - 536/9 + 16*[Zeta[2]])*Lqf + (44/3)*
     Lqf^2)*CF*CA
      + ((32 - 128*[Zeta[2]])*Lqf)*CF^2
      )
     + ...

, что дает

      ...
   + LNb * (
      + { - 224/27 + ( - 8/3)*Lqf^2 + (80/9)*Lqf}*CF*NF
      + {1616/27 - 56*[Zeta[3]] + ( - 536/9 + 16*[Zeta[2]])*Lqf + (44/3}*
     Lqf^2)*CF*CA
      + {(32 - 128*[Zeta[2]])*Lqf}*CF^2
      )
     + ...

в отличие от

      ...
   + LNb * {
      + ( - 224/27 + ( - 8/3)*Lqf^2 + (80/9)*Lqf)*CF*NF
      + (1616/27 - 56*[Zeta[3]] + ( - 536/9 + 16*[Zeta[2]])*Lqf + (44/3)*
     Lqf^2)*CF*CA
      + ((32 - 128*[Zeta[2]])*Lqf)*CF^2
      }
     + ...

, тогда как я знаю, как этого избежать, напримерЯ могу объединить строки так, чтобы они превратились в одну строку, а затем я могу использовать команду для замены самых внешних (...) на {...}.Однако у них есть некоторые другие последствия, не относящиеся к этой проблеме.

Мой главный запрос не состоит в том, чтобы разобраться в этих примерах, а в том, чтобы понять, возможно ли обнаружить и заменить строки, содержащие только один символ ) вфайл и ничего больше, где файл может иметь много других вхождений ) с некоторыми символами, которые будут неповрежденными.

Ответы [ 4 ]

0 голосов
/ 26 ноября 2018

Вы можете использовать awk, если хотите, чтобы у вас было ощущение, что у вас появилось немного больше ощущения о том, что происходит:

awk '(NF==1)&&($1==")") { sub(/\)/,"}") } 1'

Что гласит: если строка содержит одно поле и это полеэто персонаж")", затем замените в этой строке скобку на то, что вы хотите.

0 голосов
/ 25 ноября 2018

Это может работать для вас (GNU sed):

sed 's/)/&/2;t;s//}/' file

Заменить второе вхождение ) на себя и выручить, в противном случае заменить его на }.

0 голосов
/ 26 ноября 2018

С любым POSIX sed:

$ sed 's/^\([[:space:]]*\))\([[:space:]]*\)$/\1}\2/' file
exp =  ... +
     (    x
        + 2*(y)
        + z
      }
       + ...
0 голосов
/ 25 ноября 2018

Вы можете использовать что-то вроде этого:

sed -e 's/(\(.*\))/{\1}/g'

, которое всегда заменит крайние парены на { }, например:

$ echo 'foo ( 1 + ((f)) )' | sed -e 's/(\(.*\))/{\1}/g'
foo { 1 + ((f)) }

или что-то вроде этого, котороевсегда будет заменять самый внутренний parens:

sed -e 's/(\([^()]*\))/{\1}/'

Например,

$ echo 'foo ( 1 + ((f)) )' | sed -e 's/(\([^()]*\))/{\1}/g'
foo ( 1 + ({f}) )

Или точное поведение, указанное вами в вашем вопросе:

$ echo 'foo ( 1 + ((f)) )' | sed -e 's/\((.*\))/\1}/g'
foo ( 1 + ((f)) }

Вы не можете сделать правильную замену скобок одним регулярным выражением, это должен быть какой-то итерационный процесс.Это потому, что вы не можете считать с регулярными выражениями.

...