awk - проверка скобок - PullRequest
       9

awk - проверка скобок

2 голосов
/ 19 апреля 2010

Я ищу скрипт в awk, который проверит правильность размещения скобок. используются квадратные скобки {} [] и () все скобки должны быть закрыты, и скобки не могут быть смешаны, недопустимый пример: ([)]

Ответы [ 2 ]

2 голосов
/ 12 декабря 2010

Если то, что вы пытаетесь сделать, относится к языку общего назначения, то это нетривиальная проблема.

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

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

Было бы полезно знать язык, который вы хотите проверить.


Если я возьму гипотезу об отсутствии шума, т. Е. Что все скобки являются полезными скобками, моя стратегия будет итеративной:

Я бы просто искал и удалил все пары внутренних скобок: те, которые не содержат скобок внутри. Лучше всего это сделать, свернув все строки в одну длинную строку (и найти механизм для добавления ссылок на строки, если вам понадобится получить эту информацию). В этом случае поиск и замена довольно просты:

Требуется массив:

B["("]=")"; B["["]="]"; B["{"]="}"

И цикл через эти элементы:

for (b in B) {gsub("[" b "][^][(){}]*[" B[b] "]", "", $0)}

Мой тестовый файл выглядит следующим образом:

#!/bin/awk

($1 == "PID") {
  fo (i=1; i<NF; i++)
  {
    F[$i] = i
  }
}

($1 + 0) > 0 {
  count("VIRT")
  count("RES")
  count("SHR")
  count("%MEM")
}

END {
  pintf "VIRT=\t%12d\nRES=\t%12d\nSHR=\t%12d\n%%MEM=\t%5.1f%%\n", C["VIRT"], C["RES"], C["SHR"], C["%MEM"]
}

function count(c[)
{
  f=F[c];

  if ($f ~ /m$/)
  {
    $f = ($f+0) * 1024
  }

  C[c]+=($f+0)
}

Мой полный сценарий (без ссылки на строку) выглядит следующим образом:

cat test-file-for-brackets.txt | \
  tr -d '\r\n' | \
  awk \
  '
    BEGIN {
      B["("]=")";
      B["["]="]";
      B["{"]="}"
    }
    {
      m=1;
      while(m>0)
      {
        m=0;
        for (b in B)
        {
          m+=gsub("[" b "][^][(){}]*[" B[b] "]", "", $0)
        }
      };
      print
    }
  '

Вывод этого скрипта останавливается на самых недопустимых скобках. Но будьте осторожны: 1 / этот скрипт не будет работать с скобками в комментариях, регулярных выражениях или строках, 2 / он не сообщает, где в исходном файле находится проблема, 3 / хотя он удалит все сбалансированные пары, которые он останавливает в самой внутренней части ошибки и сохраняет все скобки.

Пункт 3 /, вероятно, является пригодным для использования результатом, хотя я не уверен в том, какой механизм отчетности вы имели в виду.

Точка 2 / относительно проста в реализации, но на ее создание уходит более нескольких минут, поэтому я предоставлю вам возможность разобраться.

Точка 1 / сложная, потому что вы входите в совершенно новую сферу конкурирующих, иногда вложенных, начала и конца или специальных правил цитирования для специальных символов ...

1 голос
/ 19 апреля 2010

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

awk не подходящий инструмент для этой работы. Я бы использовал язык сценариев общего назначения (Perl / Tcl / etc).

...