我正在尝试使用在 eclipse 启动之前运行的批处理脚本使可移植的 pyDev 自动设置 python 解释器。我遇到了以下 bash 脚本来做到这一点,但我无法将其转换为批处理(我熟悉):
PYTHONPATH=/my/extra/python/modules python /my/eclipse/plugins/org.python.pydev_*/PySrc/interpreterInfo.py 2>/dev/null | sed 's/INS_PATH$//g;s/OUT_PATH$//g;s/^EXECUTABLE:/Executable\:/g' | tr -d 'n' | cat <(echo -en 'eclipse.preferences.version=1nINTERPRETER_PATH_NEW=Name:python:EndName:') - <(echo '&&&&&') >/my/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs
我尝试将其分解以查看在哪里替换/管道,但这没有意义:
PYTHONPATH= App/Eclipse/plugins/org.python.pydev_*/PySrc/interpreterInfo.py 2> /dev/null
|sed ' s/ INS_PATH$/ / g; REM Delete all instances of INS_PATH that are at the end of a line
s/ OUT_PATH$/ / g; REM Delete all instances of OUT_PATH that are at the end of a line
s/ ^EXECUTABLE:/ Executable\:/ g REM Replace all instances of "nEXECUTABLE:" that are at the beginning of a line with "Executable:"
'
|tr -d 'n'
|cat <(echo -en 'eclipse.preferences.version= 1 n INTERPRETER_PATH_NEW= Name:python:EndName:') - <(echo '&&&&&')
>/my/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs
最令人困惑的部分之一是冒号的奇怪使用以及">/"与"\">的使用。 查看配置文件,我看到osgi.framework=file:plugins/org.eclipse.osgi_3.8.0.v20120529-1548.jar
我试图格式化"原始"以使其更具可读性。我将尝试解释从那里发生的事情:
PYTHONPATH=/my/extra/python/modules
python /my/eclipse/plugins/org.python.pydev_*/PySrc/interpreterInfo.py 2>/dev/null |
sed '
s/INS_PATH$//g;
s/OUT_PATH$//g;
s/^EXECUTABLE:/Executable\:/g
' |
tr -d 'n' |
cat
<(
echo -en 'eclipse.preferences.version=1nINTERPRETER_PATH_NEW=Name:python:EndName:'
)
-
<(echo '&&&&&')
>/my/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs
现在,让我们逐节查看一下以理解它。为了完整起见,我将介绍所有内容,包括我希望您已经知道的那些部分。
PYTHONPATH=/my/extra/python/modules
这是设置变量PYTHONPATH
,从上下文来看,我希望它告诉 python 在哪里寻找模块。因为我们在与命令相同的"行"中指定它,所以会发生两件事:
- 变量会自动导出到环境
- 该变量仅针对正在运行的单个命令设置(即:仅"第一个"命令,而不是整个管道,并且它不会在 shell 的环境中供后续命令使用)
接下来,主命令:
python /my/eclipse/plugins/org.python.pydev_*/PySrc/interpreterInfo.py 2>/dev/null |
这里运行"python"解释器,并传递interpreterInfo.py
脚本来执行。
_*
意味着我们没有指定我们想要的特定版本org.python.pydev
(假设只会找到一个版本,并且所有版本的行为都相似)。
2>/dev/null
意味着 stderr 上的任何输出(错误和调试信息通常通过管道传输)都将被忽略(管道传输到无处)。
现在它的肉:
sed '
s/INS_PATH$//g;
s/OUT_PATH$//g;
s/^EXECUTABLE:/Executable\:/g
' |
这做了三件事。前两个是相似的:INS_PATH
和OUT_PATH
从行的末尾删除。接下来,以及您询问的第一部分,:
字符替换为:
.如果:
是目标,为什么要双\
?这主要是由于学究。尽管:
不是有效的转义序列,因此大多数sed
会将其解释为文字标记转义序列的开始,因此指定您希望
sed
输出文字的规范方法是将其指定为
\
。因此,对于序列:
,它被指定为\:
。
每个替换命令末尾的/g
表示"全局替换",即:每次找到匹配项时,而不仅仅是第一次。
下一行很简单:
tr -d 'n' |
这将删除输出中的所有换行符。如果我理解正确,这会导致在一行上:
分隔的路径列表。
回到可能需要解释的部分:
cat
<(
echo -en 'eclipse.preferences.version=1nINTERPRETER_PATH_NEW=Name:python:EndName:'
)
-
<(echo '&&&&&')
>/my/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs
一下子要经历很多事情。让我们总结一下:
cat input-one input-two input-n > output
cat
将多个输入组合("连接")为单个输出。这实际上是cat
命令的预期用途,尽管您可能会看到它更常用于输出单个输入,例如:cat input-one
。
<( some-command )
运行some-command
并将其输出重定向到文件描述符中,其路径 (/dev/fd/N
) 在<( ... )
最初所在的上下文中用作参数传递。例如:cat <( echo foo )
会运行一个类似于cat /dev/fd/64
和echo foo
的命令,将echo foo
的输出重定向到文件描述符64
,供cat
读取。输出是foo
,就像直接运行echo
一样。
现在,将以下两件事结合起来:
cat <( some-command ) some-input <( some-other-command )
这会将some-command
的输出、some-input
的内容和some-other-command
的输出合并到一个流中。在您正在使用的脚本中,这些都合并到单个输出文件中。
那么实际为此输出构建的内容呢?让我们也逐行看一下:
<(
echo -en 'eclipse.preferences.version=1nINTERPRETER_PATH_NEW=Name:python:EndName:'
)
这将输出文本:
eclipse.preferences.version=1
INTERPRETER_PATH_NEW=Name:python:EndName:
echo -e
的意思是"解释反斜杠转义序列",因此n
扩展为换行符。echo -n
表示"不要以换行符结束输出",因此接下来的任何内容都是同一行的一部分。在这种情况下,这意味着接下来连接的任何内容都将成为INTERPRETER_PATH_NEW=
行的一部分。
-
-
是"从标准输入读取"的简写,如果您单独运行cat
,这是默认值。许多命令都使用此速记,但对于那些不使用的命令,另一种指定此方法的方法是/dev/stdin
。它的意思是"读取通过管道传输到此命令的内容",即:来自tr
的输出,它本身默认为从sed
读取输出,默认为从python
读取输出。
<(echo '&&&&&')
这将以五个&
字符和一个换行符结束流。我实际上不知道这其中的原因,所以也许有人可以评论来填写我。
>/my/workspace/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.python.pydev.prefs
作为最后一步,所有输出都重定向(通过>
符号)到文件,org.python.pydev.prefs
.
有了对正在发生的事情的大概述,现在是时候回答您询问的讨厌的细节了:
为什么所有字符?
好吧,就像我们在 sed 中转义一样,我们也在
.prefs
文件中转义:
。.prefs
文件中的:
似乎意味着"文字:
",就像 sed 中的\
指定文字一样。
/
角色呢?
/
是UNIX系统(包括现代Mac OS,即OSX)中的目录分隔符。在 Windows 系统上,使用。如上所述,在许多语言中,
也用作转义字符,因此要指定文字
,您可能需要将其编写为
\
。这没有硬性规定。一些跨平台语言意识到这个问题,也允许/
在Windows上用作目录分隔符。
我希望这能澄清问题。如果还有其他需要解释的地方,请告诉我,我将尝试编辑我的答案以添加其他信息。