bash.py 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. #!/usr/bin/env python
  2. # License: GPLv3 Copyright: 2022, Kovid Goyal <kovid at kovidgoyal.net>
  3. from typing import Dict, List, Tuple
  4. from .utils import shlex_split
  5. def decode_ansi_c_quoted_string(text: str) -> str:
  6. return next(shlex_split(text, True))
  7. def decode_double_quoted_string(text: str, pos: int) -> Tuple[str, int]:
  8. escapes = r'"\$`'
  9. buf: List[str] = []
  10. a = buf.append
  11. while pos < len(text):
  12. ch = text[pos]
  13. pos += 1
  14. if ch == '\\':
  15. if text[pos] in escapes:
  16. a(text[pos])
  17. pos += 1
  18. continue
  19. a(ch)
  20. elif ch == '"':
  21. break
  22. else:
  23. a(ch)
  24. return ''.join(buf), pos
  25. def parse_modern_bash_env(text: str) -> Dict[str, str]:
  26. ans = {}
  27. for line in text.splitlines():
  28. idx = line.find('=')
  29. if idx < 0:
  30. break
  31. key = line[:idx].rpartition(' ')[2]
  32. val = line[idx+1:]
  33. if val.startswith('"'):
  34. val = decode_double_quoted_string(val, 1)[0]
  35. else:
  36. val = decode_ansi_c_quoted_string(val)
  37. ans[key] = val
  38. return ans
  39. def parse_bash_env(text: str, bash_version: str) -> Dict[str, str]:
  40. # See https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
  41. parts = bash_version.split('.')
  42. bv = tuple(map(int, parts[:2]))
  43. if bv >= (5, 2):
  44. return parse_modern_bash_env(text)
  45. ans = {}
  46. pos = 0
  47. while pos < len(text):
  48. idx = text.find('="', pos)
  49. if idx < 0:
  50. break
  51. i = text.rfind(' ', 0, idx)
  52. if i < 0:
  53. break
  54. key = text[i+1:idx]
  55. pos = idx + 2
  56. ans[key], pos = decode_double_quoted_string(text, pos)
  57. return ans