0

I have multiple .txt files in a directory. Here is a sample of one of my .txt files:

kkkkk;

  select xx("xE'", PUT(xx.xxxx.),"'") jdfjhf:jhfjj from xxxx_x_xx_L ;
quit; 

/* 1.xxxxx FROM xxxx_x_Ex_x */ 
proc sql; ("TRUuuuth");
hhhjhfjs as fdsjfsj:
select * from djfkjd to jfkjs
(
SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and 
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))
 );


jjjjjj;

  select xx("xE'", PUT(xx.xxxx.),"'") jdfjhf:jhfjj from xxxx_x_xx_L ;
quit; 

/* 1.xxxxx FROM xxxx_x_Ex_x */ ()
proc sql; ("CUuuiiiiuth");
hhhjhfjs as fdsjfsj:
select * from djfkjd to jfkjs
(SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and 
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))(( ))
 );

I am trying to extract all sentences in nested parentheses, in my .txt files.

I have tried multiple methods like stacking parentheses but I get an error which says "list index out of range" when the code parses through one of the .txt files. I'm guessing its because there is nothing written in the brackets.

I have been trying it with regex too, using this code:

with open('lan sample text file.txt','r') as fd:
    lines = fd.read()

    check = set()
    check.add("Select")
    check.add("select")
    check.add("SELECT")
    check.add("from")
    check.add("FROM")
    check.add("From")
    items=re.findall("(\(.*)\)",lines,re.MULTILINE)
    for x in items:
        print(x)

but my output is:

("xE'", PUT(xx.xxxx.),"'"
("TRUuuuth"
((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.
(xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.)
("xE'", PUT(xx.xxxx.),"'"
("CUuuiiiiuth"
((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.
(xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.)

My desired output should look something like this:

("xE'", PUT(xx.xxxx.),"'")
("TRUuuuth")
(
SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and 
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))
 )
("xE'", PUT(xx.xxxx.),"'")
("CUuuiiiiuth")
(SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and 
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))(( ))
 )
  • Does this answer your question? [Python: How to match nested parentheses with regex?](https://stackoverflow.com/questions/5454322/python-how-to-match-nested-parentheses-with-regex) – Booboo Nov 18 '19 at 13:50
  • @RonaldAaronson no it did not......that question is seemingly less complicated than what i have. –  Nov 18 '19 at 13:51

2 Answers2

0

I would say my solution is not the optimised one, but it will solve your problem.

Solution (Just replace test.txt with your file name)

result = []
with open('test.txt','r') as fd:
    # To keep track of '(' and ')' parentheses
    parentheses_stack = []
    # To keep track of complete word wrapped by ()
    complete_word = []
    # Iterate through each line in file
    for words in fd.readlines():
        # Iterate each character in a line
        for char in list(words):
            # Initialise the parentheses_stack when you find the first open '(' 
            if char == '(':
                parentheses_stack.append(char)
            # Pop one open '(' from parentheses_stack when you find a ')'
            if char == ')':
                if not parentheses_stack = []:
                    parentheses_stack.pop()
                if parentheses_stack == []:
                    complete_word.append(char)
            # Collect characters in between the first '(' and last ')'
            if not parentheses_stack == []:
                complete_word.append(char)
            else:
                if not complete_word == []:
                    # Push the complete_word once you poped all '(' from parentheses_stack
                    result.append(''.join(complete_word))
                    complete_word = []



for res in result:
    print(res)

Result:

WS:python rameshrv$ python3 /Users/rameshrv/Documents/python/test.py
("xE'", PUT(xx.xxxx.),"'")
("TRUuuuth")
(
SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and 
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))
 )
("xE'", PUT(xx.xxxx.),"'")
()
("CUuuiiiiuth")
(SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and 
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))(( ))
 )
Ramesh RV
  • 72
  • 7
  • hey Ramesh! It does work! But i dont know if it'll work on my actual working file. I will get back to you when I've tried it at work tomorrow, but thank you so much for trying to resolve my situation. I truly appreciate it! I'll mark it as the answer once it works out! *fingers crossed* –  Nov 18 '19 at 14:09
  • my code has some minor bugs and i am trying to fix them. Will upload the clean code once i am done with the bugs. – Ramesh RV Nov 18 '19 at 14:11
  • Hi Ramesh, what if I run into an error that says: "IndexError: pop from empty list" when running your code? How could I work my way around this error? –  Nov 25 '19 at 09:44
  • Then you need to add a condition before parentheses_stack.pop() to check whether the parentheses_stack is empty. – Ramesh RV Dec 02 '19 at 11:07
  • i tried to put if words != "": before it but the error still happens –  Dec 02 '19 at 14:52
  • i edited the answer to handle the IndexError. Now it shouldn't throw any Exceptions. – Ramesh RV Dec 03 '19 at 15:42
0

As I said, this is a duplicate of Python: How to match nested parentheses with regex?, which shows several methods of handling nested parentheses, not all of which are regex-based. One way does require the regex module from the PYPI repository. If text contains the contents of the file, then the following should do what you want:

import regex as re

text = """kkkkk;

  select xx("xE'", PUT(xx.xxxx.),"'") jdfjhf:jhfjj from xxxx_x_xx_L ;
quit;

/* 1.xxxxx FROM xxxx_x_Ex_x */
proc sql; ("TRUuuuth");
hhhjhfjs as fdsjfsj:
select * from djfkjd to jfkjs
(
SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))
 );


jjjjjj;

  select xx("xE'", PUT(xx.xxxx.),"'") jdfjhf:jhfjj from xxxx_x_xx_L ;
quit;

/* 1.xxxxx FROM xxxx_x_Ex_x */ ()
proc sql; ("CUuuiiiiuth");
hhhjhfjs as fdsjfsj:
select * from djfkjd to jfkjs
(SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))(( ))
 );"""    

regex = re.compile(r"""
(?<rec> #capturing group rec
 \( #open parenthesis
 (?: #non-capturing group
    [^()]++ #anything but parenthesis one or more times without backtracking
  | #or
    (?&rec) #recursive substitute of group rec
 )*
 \) #close parenthesis
)
""", flags=re.VERBOSE)

for m in regex.finditer(text):
    groups = m.captures('rec')
    group = groups[-1] # the last group is the outermost nesting
    if re.match(r'^\(+\s*\)+$', group):
        continue # not interested in empty parentheses such as '( )'
    print(group)

Prints:

("xE'", PUT(xx.xxxx.),"'")
("TRUuuuth")
(
SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))
 )
("xE'", PUT(xx.xxxx.),"'")
("CUuuiiiiuth")
(SELECT abc AS abc1, abc_2_ AS efg, abc_fg, fkdkfj_vv, jjsflkl_ff, fjkdsf_jfkj
    FROM &xxx..xxx_xxx_xxE
where ((xxx(xx_ix as format 'xxxx-xx') gff &jfjfsj_jfjfj.) and
      (xxx(xx_ix as format 'xxxx-xx') lec &jgjsd_vnv.))(( ))
 )
Booboo
  • 38,656
  • 3
  • 37
  • 60
  • Hi Ronald, this did not work, I ran into an error-> "error: unknown extension ? –  Nov 20 '19 at 13:58
  • @pysduck Did you code `import regex as re`, as iI have it in the first line of the code above? You *do* need the `regex` package from the PyPi repository. I also added the definition of string variable `text`, just to make everything explicit. – Booboo Nov 20 '19 at 14:07
  • ohhhh. I do not have that package. Sorry for not understanding that! But thank you for showing me something new:) –  Nov 20 '19 at 14:19
  • 1
    @psyduck It's easy to install: `pip install regex`. It also fixes some bugs in the standard `re` package depending on what version of Python you are running. – Booboo Nov 20 '19 at 14:22