Removing lines from a file using python
Question: > **Possible Duplicate:**  
>  [Python 3 regular expression to find multiline
> comment](http://stackoverflow.com/questions/7081882/python-3-regular-
> expression-to-find-multiline-comment)

I need some inputs on how this can be done,really appreciate your inputs,I
looked at other posts but none of them matches my requirement.

[How to remove line from the file in
python](http://stackoverflow.com/questions/7276454/how-to-remove-line-from-
the-file-in-python) http://stackoverflow.com/questions/2064184/remove-lines-
from-textfile-with-python

I need to match a multi-line comment in a file based on a input string
provided.

Example:-

Lets say if the file "test.txt" has the following comment,if inputstring="This
is a test, script written" this comment needs to be deleted from the file

    
    
    import os
    import sys
    
    import re
    import fnmatch
    
    def find_and_remove(haystack, needle):
        pattern = re.compile(r'/\*.*?'+ needle + '.*?\*/', re.DOTALL)
        return re.sub(pattern, "", haystack)
    
    for path,dirs,files in os.walk(sys.argv[1]):
        for fname in files:
            for pat in ['*.cpp','*.c','*.h','*.txt']:
                if fnmatch.fnmatch(fname,pat):
                    fullname = os.path.join(path,fname)
                    with open(fullname, "r") as f:
                        find_and_remove(f, r"This is a test, script written")
    

Error:-

    
    
    Traceback (most recent call last):
      File "comment.py", line 16, in <module>
        find_and_remove(f, r"This is a test, script written")
      File "comment.py", line 8, in find_and_remove
        return re.sub(pattern, "", haystack)
      File "/usr/lib/python2.6/re.py", line 151, in sub
        return _compile(pattern, 0).sub(repl, string, count)
    TypeError: expected string or buffer
    


Answer: The first thing that came to mind when I saw the question was "state machine",
and whenever I think "state machine" in python, the first thing that comes to
mind is "generator" a.k.a. yield:

    
    
    def skip_comments(f):
        """
        Emit all the lines that are not part of a multi-line comment.
        """
        is_comment = False
    
        for line in f:
            if line.strip().startswith('/*'):
                is_comment = True
    
            if line.strip().endswith('*/'): 
                is_comment = False
            elif is_comment:
                pass
            else:
                yield line
    
    
    def print_file(file_name):
        with file(file_name, 'r') as f:
            skipper = skip_comments(f)
    
            for line in skipper:
                print line,
    

EDIT: user1927396 upped the ante by specifying that it's just a specific block
to exclude, that contains specific text. Since it's inside the comment block,
we won't know up front if we need to reject the block or not.

My first thought was buffer. Ack. Poo. My second thought was a haunting
refrain I've been carrying in my head for 15 years and never used until now:
"stack of state machines" ...

    
    
    def squelch_comment(f, first_line, exclude_if):
        """
        Comment is a multi-line comment that we may want to suppress
        """
        comment = [first_line]
    
        if not first_line.strip().endswith('*/'):
            for line in f:
    
                if exclude_if in line:
                    comment = None
    
                if comment and len(comment):
                    comment.append(line)
    
                if line.strip().endswith('*/'):
                    break
    
        if comment:
            for comment_line in comment:
                yield '...' + comment_line
    
    
    def skip_comments(f):
        """
        Emit all the lines that are not part of a multi-line comment.
        """
        for line in f:
            if line.strip().startswith('/*'):
                # hand off to the nested, comment-handling, state machine
                for comment_line in squelch_comment(f, line, 'This is a test'):
                    yield comment_line
            else:
                yield line
    
    
    def print_file(file_name):
        with file(file_name, 'r') as f:
            for line in skip_comments(f):
                print line,
    

