def uncomment(name, regex, char='#', backup='.bak'):
    '''
    Uncomment specified commented lines in a file

    name
        The full path to the file to be edited
    regex
        A regular expression used to find the lines that are to be uncommented.
        This regex should not include the comment character. A leading ``^``
        character will be stripped for convenience (for easily switching
        between comment() and uncomment()).  The regex will be searched for
        from the beginning of the line, ignoring leading spaces (we prepend
        '^[ \\t]*')
    char : ``#``
        The character to remove in order to uncomment a line
    backup : ``.bak``
        The file will be backed up before edit with this file extension;

        .. warning::

            This backup will be overwritten each time ``sed`` / ``comment`` /
            ``uncomment`` is called. Meaning the backup will only be useful
            after the first invocation.

        Set to False/None to not keep a backup.

    Usage:

    .. code-block:: yaml

        /etc/adduser.conf:
          file.uncomment:
            - regex: EXTRA_GROUPS

    .. versionadded:: 0.9.5
    '''
    name = os.path.expanduser(name)

    ret = {'name': name,
           'changes': {},
           'result': False,
           'comment': ''}
    if not name:
        return _error(ret, 'Must provide name to file.uncomment')

    check_res, check_msg = _check_file(name)
    if not check_res:
        return _error(ret, check_msg)

    # Make sure the pattern appears in the file
    if __salt__['file.search'](
            name,
            '{0}[ \t]*{1}'.format(char, regex.lstrip('^')),
            multiline=True):
        # Line exists and is commented
        pass
    elif __salt__['file.search'](
            name,
            '^[ \t]*{0}'.format(regex.lstrip('^')),
            multiline=True):
        ret['comment'] = 'Pattern already uncommented'
        ret['result'] = True
        return ret
    else:
        return _error(ret, '{0}: Pattern not found'.format(regex))

    if __opts__['test']:
        ret['changes'][name] = 'updated'
        ret['comment'] = 'File {0} is set to be updated'.format(name)
        ret['result'] = None
        return ret

    with salt.utils.files.fopen(name, 'rb') as fp_:
        slines = salt.utils.data.decode(fp_.readlines())

    # Perform the edit
    __salt__['file.comment_line'](name, regex, char, False, backup)

    with salt.utils.files.fopen(name, 'rb') as fp_:
        nlines = salt.utils.data.decode(fp_.readlines())

    # Check the result
    ret['result'] = __salt__['file.search'](
        name,
        '^[ \t]*{0}'.format(regex.lstrip('^')),
        multiline=True
    )

    if slines != nlines:
        if not __utils__['files.is_text'](name):
            ret['changes']['diff'] = 'Replace binary file'
        else:
            # Changes happened, add them
            ret['changes']['diff'] = (
                ''.join(difflib.unified_diff(slines, nlines))
            )

    if ret['result']:
        ret['comment'] = 'Uncommented lines successfully'
    else:
        ret['comment'] = 'Expected uncommented lines not found'

    return ret
def uncomment ( name , regex , char = '#' , backup = '.bak' ) : name = os . path . expanduser ( name ) ret = { 'name' : name , 'changes' : { } , 'result' : False , 'comment' : '' } if not name : return _error ( ret , 'Must provide name to file.uncomment' ) check_res , check_msg = _check_file ( name ) if not check_res : return _error ( ret , check_msg ) if __salt__ [ 'file.search' ] ( name , '{0}[ \t]*{1}' . format ( char , regex . lstrip ( '^' ) ) , multiline = True ) : pass elif __salt__ [ 'file.search' ] ( name , '^[ \t]*{0}' . format ( regex . lstrip ( '^' ) ) , multiline = True ) : ret [ 'comment' ] = 'Pattern already uncommented' ret [ 'result' ] = True return ret else : return _error ( ret , '{0}: Pattern not found' . format ( regex ) ) if __opts__ [ 'test' ] : ret [ 'changes' ] [ name ] = 'updated' ret [ 'comment' ] = 'File {0} is set to be updated' . format ( name ) ret [ 'result' ] = None return ret with salt . utils . files . fopen ( name , 'rb' ) as fp_ : slines = salt . utils . data . decode ( fp_ . readlines ( ) ) __salt__ [ 'file.comment_line' ] ( name , regex , char , False , backup ) with salt . utils . files . fopen ( name , 'rb' ) as fp_ : nlines = salt . utils . data . decode ( fp_ . readlines ( ) ) ret [ 'result' ] = __salt__ [ 'file.search' ] ( name , '^[ \t]*{0}' . format ( regex . lstrip ( '^' ) ) , multiline = True ) if slines != nlines : if not __utils__ [ 'files.is_text' ] ( name ) : ret [ 'changes' ] [ 'diff' ] = 'Replace binary file' else : ret [ 'changes' ] [ 'diff' ] = ( '' . join ( difflib . unified_diff ( slines , nlines ) ) ) if ret [ 'result' ] : ret [ 'comment' ] = 'Uncommented lines successfully' else : ret [ 'comment' ] = 'Expected uncommented lines not found' return ret
Uncomment specified commented lines in a file

    name
        The full path to the file to be edited
    regex
        A regular expression used to find the lines that are to be uncommented.
        This regex should not include the comment character. A leading ``^``
        character will be stripped for convenience (for easily switching
        between comment() and uncomment()).  The regex will be searched for
        from the beginning of the line, ignoring leading spaces (we prepend
        '^[ \\t]*')
    char : ``#``
        The character to remove in order to uncomment a line
    backup : ``.bak``
        The file will be backed up before edit with this file extension;

        .. warning::

            This backup will be overwritten each time ``sed`` / ``comment`` /
            ``uncomment`` is called. Meaning the backup will only be useful
            after the first invocation.

        Set to False/None to not keep a backup.

    Usage:

    .. code-block:: yaml

        /etc/adduser.conf:
          file.uncomment:
            - regex: EXTRA_GROUPS

    .. versionadded:: 0.9.5