import re


def replace_entities(entities, pattern):
    """
    Replaces all entity names in a given pattern with the corresponding
    values provided by entities.

    Args:
        entities (dict): A dictionary mapping entity names to entity values.
        pattern (str): A path pattern that contains entity names denoted
            by curly braces. Optional portions denoted by square braces.
            For example: 'sub-{subject}/[var-{name}/]{id}.csv'
            Accepted entity values, using regex matching, denoted within angle
            brackets.
            For example: 'sub-{subject<01|02>}/{task}.csv'

    Returns:
        A new string with the entity values inserted where entity names
        were denoted in the provided pattern.
    """
    ents = re.findall('\{(.*?)\}', pattern)
    new_path = pattern
    for ent in ents:
        match = re.search('([^|<]+)(<.*?>)?(\|.*)?', ent)
        if match is None:
            return None
        name, valid, default = match.groups()
        default = default[1:] if default is not None else default

        if name in entities:
            if valid is not None:
                ent_val = str(entities[name])
                if not re.match(valid[1:-1], ent_val):
                    if default is None:
                        return None
                    entities[name] = default

        ent_val = entities.get(name, default)
        if ent_val is None:
            return None
        new_path = new_path.replace('{%s}' % ent, str(ent_val))

    return new_path