Awk - parentheses checking
If what you are trying to do is in a general purpose language, then this is not a trivial problem.
For starters, you have to worry about comments and lines. If you want to test this in a programming language that uses regular expressions, this again makes your quest more difficult.
So, before I can come and give you any advice on your question, I need to know the limits of your problem area. If you can guarantee that there are no strings, no comments, no regexes to worry about - or, more generally, nowhere in your code that can be used in parentheses other than the ones you check for balance , it will make life a lot easier.
It would be helpful to know the language you want to test.
If I take the hypothesis that there is no noise, i.e. all parentheses are useful parentheses, my strategy will be iterative:
I would just search and remove all the inner pairs of brackets: the ones that do not contain brackets inside. This is best done by collapsing all lines into one long line (and find a mechanism for adding line references if you need this information). In this case, find and replace is pretty simple:
This requires an array:
B["("]=")"; B["["]="]"; B["{"]="}"
And loop through these elements:
for (b in B) {gsub("[" b "][^][(){}]*[" B[b] "]", "", $0)}
My test file looks like this:
#!/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)
}
My complete script (no line reference) looks like this:
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
}
'
The output of this script stops at the innermost illegal use of parentheses. But be careful: 1 / this script won't work with parentheses in comments, regex or lines 2 / it doesn't tell you where the original file is, problem 3 / although it will remove all balanced pairs it stops on the innermost error conditions and holds all the capturing brackets.
Point 3 / is probably a useful result, although I'm not sure about the reporting mechanism you have in mind.
Point 2 / is relatively easy to implement, but it takes more than a few minutes of work, so I'll leave that to you to figure it out.
Point 1 / is tricky because you are introducing a whole new realm of competing sometimes nested beginnings and endings or special citation rules for special characters ...
a source to share
You will need to read the file character by character. Create a stack of open brackets. When you see a closed parenthesis, you can either push the corresponding open parenthesis off the stack, or log an error where parentheses do not match.
awk is not the right tool for the job. I would use a general purpose scripting language (Perl / Tcl / etc).
a source to share