python 将Nix的配置文件bash脚本转换为Fish的Python脚本

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 将Nix的配置文件bash脚本转换为Fish的Python脚本相关的知识,希望对你有一定的参考价值。

#!/usr/bin/env python3
import re, sys, os

"""
Converts the Nix profile SH script to a Fish-compatible profile using a
simple line-by-line replace algorithm.
"""

# Regular expressions for things we need to rewrite
RE_TEST    = re.compile("\[([^\]]+)\]")
RE_EXPORT  = re.compile("^(\s*)export ([A-Z_]+)\s*=(.+)$")
RE_SET     = re.compile("^(\s*)([A-Za-z_]+)\s*=(.+)$")
RE_IF_NOT  = re.compile("(\s*)if\s+!\s+(.*)$")
RE_FI      = re.compile("^(\s*)fi(\s*)$")
RE_UNSET  = re.compile("^(\s*)unset(\s*)(.+)$")
RE_BRACKET = re.compile("\$\{([A-Z_]+)\}")
RE_WHITESPACE = re.compile("^[\s\n]+")

# Simple word-for-word rewrites
REWRITE   = {
	"elif "  : "else if ",
	"! test" : "test !",
	"; then" : ";",
	" && "   : "; and ",
	"$("     : "(",
}

def unwrap( text ):
	"""Takes a line like `"abc:def"` and returns `abc def`. This is
	useful for converting sh-like path lists to fish path lists."""
	text = text.strip()
	if len(text) > 2 and text[0] == text[-1] and text[0] == '"':
		return " ".join(text[1:-1].split(":"))
	else:
		return text

def re_replace( regexp, text, functor ):
	"""Replaces all matching instances of `regexp` in `text` by passing the
	match to the given `functor`."""
	r = []
	o = 0
	for m in regexp.finditer(text):
		r.append(text[o:m.start()])
		r.append(functor(m))
		o = m.end()
	r.append(text[o:])
	return "".join(r)

def process_line( line ):
	"""Processes the given line of Shell code, applying both the regexes
	and word substitutions."""
	nix_path = "${NIX_PATH:+$NIX_PATH:}"
	if nix_path in line:
		# Here we have a special case which is quite annoying, where a Bash
		# substitution is used with a default value.
		line = "\n".join((
			'if test -z "$NIX_PATH";',
			'     ' + process_line(line.replace(nix_path, "")),
			'else',
			'     ' + process_line(line.replace(nix_path, "$NIX_PATH:")),
			'end',
		))
		return line
	# Fish is a little bit annoying with shell expressions in strings.
	# "(id -u)" is not like "$(id -u)" in bash, but should be ""(id -u)""
	l = RE_WHITESPACE.sub("", line)
	if l.startswith("echo"):
		line = line.replace("$(", '"(').replace(")", ')"').replace('""','')
	elif l.startswith("if"):
		line = line.replace('"$(', "(").replace(')"', ")")
	elif l.startswith("__savedpath="):
		# This is a special handling of the initial path saving. Fish complains
		# about non-existing entries in PATH, so we need to filter them first.
		return "    for d in $PATH; if test -e $d; set __savedpath $__savedpath $d; end; end;"
	m = RE_IF_NOT.match(line)
	if m:
		pre = m.group(1)
		cmd = m.group(2)
		return "\n".join((
			"{0}{1}".format(pre, process_line(cmd)),
			"{0}if test ! $status -eq 0;".format(pre)
		))
	line = re_replace(RE_TEST,   line, lambda m:"test{0}".format(m.group(1)))
	line = re_replace(RE_EXPORT, line, lambda m:"{0}set -xg {1} {2}".format(m.group(1), m.group(2), unwrap(m.group(3))))
	line = re_replace(RE_SET,    line, lambda m:"{0}set -g  {1} {2}".format(m.group(1), m.group(2), unwrap(m.group(3))))
	line = re_replace(RE_UNSET,  line, lambda m:"{0}{1}".format(m.group(1), "; ".join("set -e " + _ for _ in  m.group(3).split())))
	line = re_replace(RE_FI,     line, lambda m:"{0}end{1}".format(m.group(1),m.group(2)))
	line = re_replace(RE_BRACKET,line, lambda m:"${0}".format(m.group(1)))
	for s,d in REWRITE.items(): line = line.replace(s,d)
	return line

def process( text, origin ):
	"""Processes the given text."""
	res = [
		"#!/usr/bin/env fish",
		"# --8<-- [This file is automatically generated from {0}, do not edit] ---".format(origin),
	]
	for line in text.split("\n"):
		res.append(process_line(line))
	res.append("# --8<-- EOF --- vim: readonly")
	return "\n".join(res)

if __name__ == "__main__":
	src = "~/.nix-profile/etc/profile.d/nix.sh"
	dst = "~/.config/fish/nix.fish"
	if not os.path.exists(os.path.expanduser(src)):
		sys.stderr.write("Nix does not seem to be installed, expecting {0}".format(src))
		sys.exit(-1)
	with open(os.path.expanduser(src), "rt") as f:
		t = process(f.read(), src)
		with open(os.path.expanduser(dst), "wt") as g:
			g.write(t)
		sys.stderr.write("To use Nix from Fish: source {0}".format(dst))

# EOF

以上是关于python 将Nix的配置文件bash脚本转换为Fish的Python脚本的主要内容,如果未能解决你的问题,请参考以下文章

为 *nix 创建 Python 可执行文件 [重复]

sh Bash脚本使用Applescript将目录中的所有html文件转换为docx文件。它还将标题和普通字体转换为

用于将日期和时间列转换为 .csv 中的 unix 时间戳的 Bash 脚本

检查是不是在 bash 脚本中保留了 shift

sh [sh - 递归搜索]递归移动文件#macOS #nix #Bash

在文本文件中将纪元转换为标准的bash脚本[重复]