def to_cat_replace(m, cats, indices):
    """Performs numbered category replacement in the output of a sound change.

    Args:
        m: The match object. It should have two groups, the first one a
            non-zero-length) string of digits (the number of the numbered
            category), and the second a string of word characters (the name of
            the category).
        cats: The dict of categories to use in replacement.
        indices: The dict of numbered category indices to use in replacement.
            It's keys should be of the form 'nc' + n, where n is a number, and
            it's values should be the index associated with that numbered
            category.

    Returns:
        The appropriate element of the specified category. If that element is
        '0', it is replaced with ''. If the category isn't in cats, or the
        number isn't present in indices, the original string is returned.
    """
    n, c = m.groups()
    if c in cats and n != '' and 'nc' + n in indices:
        # treat '0' as '', to allow for categories with gaps
        if cats[c][indices['nc' + n]] == '0':
            return ''
        return cats[c][indices['nc' + n]]
    return m.group(0)