def expandvars(path: AnyStr) -> AnyStr: """Expand shell variables of form $var and ${var}. Unknown variables are left unchanged.""" global _varprog, _varprogb if isinstance(path, bytes): if b'$' not in path: return path if not _varprogb: import re _varprogb = re.compile(br'\$(\w+|\{[^}]*\})', re.ASCII) search = _varprogb.search start = b'{' end = b'}' else: if '$' not in path: return path if not _varprog: import re _varprog = re.compile(r'\$(\w+|\{[^}]*\})', re.ASCII) search = _varprog.search start = '{' end = '}' i = 0 while True: m = search(path, i) if not m: break i, j = m.span(0) name = Undefined(Union[str, bytes]) name = m.group(1) if name.startswith(start) and name.endswith(end): name = name[1:-1] if isinstance(name, bytes): name = str(name, 'ASCII') if name in os.environ: tail = path[j:] value = Undefined(Union[str, bytes]) value = os.environ[name] if isinstance(path, bytes): value = value.encode('ASCII') path = path[:i] + value i = len(path) path += tail else: i = j return path