我试图格式化“原始”以使其更具可读性。我将尝试解释从那里发生的事情:
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=1\nINTERPRETER_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
意味着标准错误和调试信息通常通过管道传输的任何输出都将被忽略(管道传输到无处)。
现在它的肉:
sed '
s/INS_PATH$//g;
s/OUT_PATH$//g;
s/^EXECUTABLE:/Executable\\:/g
' |
这做了三件事。前两个是相似的:INS_PATH
并且OUT_PATH
从行的末端移除。接下来,也是您询问的第一部分,:
字符被替换为\:
. 为什么双重\\
如果\:
是目标?这主要是由于迂腐。虽然\:
不是有效的转义序列,因此大多数sed
s 会将其解释为文字\
标记Escape Sequence的开头,因此指定要sed
输出文字的规范方法\
是将其指定为\\
. 因此,对于序列\:
,它被指定为\\:
。
每个/g
替换命令末尾的 表示“全局替换”,即:每次找到匹配项,而不仅仅是第一次。
下一行很简单:
tr -d '\n' |
这将删除输出中的所有换行符。如果我理解正确,这会在\:
一行上生成一个单独的路径列表。
回到可能需要解释的部分:
cat \
<(
echo -en 'eclipse.preferences.version=1\nINTERPRETER_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
并将其输出重定向到File Descriptor,其路径 ( /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=1\nINTERPRETER_PATH_NEW=Name\:python\:EndName\:'
)
这将输出文字:
eclipse.preferences.version=1
INTERPRETER_PATH_NEW=Name\:python\:EndName\:
echo -e
表示“解释反斜杠转义序列”,因此\n
扩展为换行符。echo -n
意思是“不要用换行符结束输出”,所以接下来发生的都是同一行的一部分。在这种情况下,这意味着接下来连接的任何内容都将成为该INTERPRETER_PATH_NEW=
行的一部分。
-
A-
是“从标准输入读取”的简写,如果您自己运行,这是默认设置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 上用作目录分隔符。
我希望这能解决问题。让我知道是否还有其他需要解释的内容,我将尝试编辑我的答案以添加更多信息。