在 bash 脚本中嵌入简短的 python 脚本
Posted
技术标签:
【中文标题】在 bash 脚本中嵌入简短的 python 脚本【英文标题】:embedding short python scripts inside a bash script 【发布时间】:2021-12-07 06:21:09 【问题描述】:我想将短 python 脚本的文本嵌入到 bash 脚本中,例如我的.bash_profile
。做这种事情的最佳方法是什么?
到目前为止,我的解决方案是使用-c
选项调用python 解释器,并告诉解释器exec
从stdin
读取的任何内容。从那里,我可以构建类似以下的简单工具,允许我处理文本以在我的交互式提示中使用:
function pyexec()
echo "$(/usr/bin/python -c 'import sys; exec sys.stdin.read()')"
function traildirs()
pyexec <<END
trail=int('$1:-3')
import os
home = os.path.abspath(os.environ['HOME'])
cwd = os.environ['PWD']
if cwd.startswith(home):
cwd = cwd.replace(home, '~', 1)
parts = cwd.split('/')
joined = os.path.join(*parts[-trail:])
if len(parts) <= trail and not joined.startswith('~'):
joined = '/'+joined
print joined
END
export PS1="\h [\$(traildirs 2)] % "
不过,这种方法对我来说有点好笑,我想知道这种方法的替代方法可能是什么。
我的 bash 脚本编写技能非常初级,所以我特别想知道从 bash 解释器的角度来看我是否在做一些愚蠢的事情。
【问题讨论】:
你能更清楚地说出你真正想要做什么吗?据我所知,Python 并不是真正需要的。你可以用 shell 做大部分事情。 @ghostdog74:没有什么比我说的更深刻了;我只是一个比 bash 程序员更好的 python 程序员,而且 IMO python 通常比 bash 更强大。在 python 中实现 bash 脚本中使用的功能可能很方便,并且有时在这样做时不依赖于外部文件。我终于从 tcsh 切换到 bash(15 年后),我正试图将外壳弯曲到我的意愿/偏好。 -1:为什么不简单地创建一个 .py 模块文件?当更好的解决方案是(通常)完全停止使用 shell 时,为什么要强制 Python 进入 shell 脚本? @S.Lott:就我而言,我将 bash 脚本作为 Alfred 命令运行,但需要 Python 的拆分功能。创建 .py 文件会增加不必要的开销。 【参考方案1】:使用 bash here document
的一个问题是脚本随后会在 stdin
上传递给 Python,因此如果您想使用 Python 脚本作为过滤器,它会变得笨拙。一种替代方法是使用bash
的process substitution
,如下所示:
... | python <( echo '
code here
' ) | ...
如果脚本太长,也可以在括号内使用here document
,如下所示:
... | python <(
cat << "END"
code here
END
) | ...
在脚本内部,您可以像往常一样从/向标准 i/o 读取/写入(例如,sys.stdin.readlines
吞噬所有输入)。
此外,python -c
可以像其他答案中提到的那样使用,但这是我喜欢这样做的方式,以便很好地格式化,同时仍然尊重 Python 的缩进规则 (credits):
read -r -d '' script <<-"EOF"
code goes here prefixed by hard tab
EOF
python -c "$script"
只需确保此处文档中每一行的第一个字符是硬制表符。如果你必须把它放在一个函数中,那么我使用我在某处看到的以下技巧使其看起来对齐:
function somefunc()
read -r -d '' script <<-"----EOF"
code goes here prefixed by hard tab
----EOF
python -c "$script"
【讨论】:
为什么 0 票?如果您想在程序中使用 sys.stdin,它是这里唯一正确的答案! 这是迄今为止最好的解决方案!我还要补充一点,您可能希望在第二个示例中引用 END:cat <<'END'
以避免在 HERE 文档中转义 $ 字符和其他特殊字符。
@MichaelGoldshteyn 完成!
有人可以帮我吗。它不起作用#!/system/bin/bash function parse_plex() read -r -d '' script <<-"----EOF" import requests requests.get('https://google.com') ----EOF python -c $script parse_plex
文件“$script
周围加上双引号,例如python -c "$script"
。我会更新答案。【参考方案2】:
准备复制粘贴示例:
input="hello"
output=`python <<END
print "$input world";
END`
echo $output
【讨论】:
你能帮忙解决这个问题吗,发布在 *** 上:***.com/questions/68002623/… @AhHatem:你能帮忙解决这个问题吗,发布在 *** 上:***.com/questions/68002623/…【参考方案3】:试试这个:
#!/bin/bash
a="test"
python -c "print '$a this is a test'.title()"
【讨论】:
【参考方案4】:有时使用此处的文档不是一个好主意。另一种选择是使用 python -c:
py_script="
import xml.etree.cElementTree as ET,sys
...
"
python -c "$py_script" arg1 arg2 ...
【讨论】:
既好又简单,让您可以将 python 代码从其余 bash 代码的中间移开。还可以让您的 python 代码从标准输入读取。 @Don Li 你能帮忙解决这个问题吗,发布在 *** 上:***.com/questions/68002623/…【参考方案5】:如果您使用的是 zsh,您可以使用 zsh 的 join 和 python 标准输入选项 (python -
) 将 Python 嵌入到脚本中:
py_cmd=$(j:\n:)"$(f)$(
# You can also add comments, as long as you balance quotes
<<<'if var == "quoted text":'
<<<' print "great!"')"
catch_output=$(echo $py_cmd | python -)
您可以缩进 Python sn-p,因此在函数内部时它看起来比 EOF
或 <<END
解决方案更好。
【讨论】:
【参考方案6】:如果你需要在 bash 脚本中使用 python 的输出,你可以这样做:
#!/bin/bash
ASDF="it didn't work"
ASDF=`python <<END
ASDF = 'it worked'
print ASDF
END`
echo $ASDF
【讨论】:
注意命名heredoc标记的方式。当它在您的示例中未引用时,shell 扩展将在 heredoc 字符串中发生。例如,如果您的 python 代码仅包含print '$SHELL'
,则输出将是 /bin/bash
或您的外壳恰好是什么。如果将第一行更改为python - <<'END'
,则输出将为$SHELL
。如果您要复制和粘贴现有代码以嵌入到 bash 脚本中,那么您几乎肯定不希望 shell 替换——您希望代码以与未嵌入 bash 脚本时相同的方式运行,对吧?跨度>
@desgua:你能帮忙解决这个问题吗,发布在 *** 上:***.com/questions/68002623/…【参考方案7】:
有趣...我现在也想要一个答案 ;-)
他不是在问如何在 bash 脚本中执行 python 代码,而是实际上让 python 设置了环境变量。
把它放在一个 bash 脚本中,并试着让它说“它有效”。
export ASDF="it didn't work"
python <<END
import os
os.environ['ASDF'] = 'it worked'
END
echo $ASDF
问题是 python 在环境的副本中执行。在 python 退出后,不会看到对该环境的任何更改。
如果有解决方案,我也很想看看。
【讨论】:
这并不是我真正想要的,我很确定你不能(直接)从子进程获取环境变量或改变父进程的环境变量(直接)。但是,您可以eval
bash 脚本中的 python 脚本的输出,从而执行任意语句、设置环境变量或执行您可能喜欢的任何其他操作。
@Eric:如果您真的想要答案,请发布您自己的问题。
马特,抱歉...我简单地查看了您的 python 脚本,发现您正在使用 os.environ 做一些事情,并认为这就是您正在做的事情。我的错。
您可以通过结合 bash 变量和 python 输出来管理它。请参阅下面的答案。
@eric.frederich 你能帮忙解决这个问题吗,发布在 *** 上:***.com/questions/68002623/…【参考方案8】:
python 解释器在命令行中接受 -
作为 stdin
的同义词,因此您可以将 pyexec 调用替换为:
python - <<END
参见命令行参考here。
【讨论】:
嗯——我在 python 手册页上进行了文本搜索,但文本stdin
不在那里。不过,仔细观察,“标准输入”是。呵呵。
同意heredoc方法可以工作。但是有一些事情需要注意:(1)如果heredoc标记(在Ned的例子中为END
)出现在Python脚本的第0列,heredoc将提前结束; (2)heredoc 标记的变化(带或不带前导-
)会影响制表符和空格是否被保留; (3) 开启变量扩展时 Python 和 bash 之间的语法重叠(heredoc 标记未引用),例如$1
可以合法地出现在 Python 字符串格式说明符中,但如果未引用 heredoc 标记,则将替换为 bash 命令行参数。
注意命名heredoc标记的方式。当它在您的示例中未引用时,shell 扩展将在 heredoc 字符串中发生。例如,如果您的 python 代码仅包含 print '$SHELL'
,则输出将是 /bin/bash
或您的 shell 恰好是什么。如果将第一行更改为python - <<'END'
,则输出将为$SHELL
。如果您要复制和粘贴现有代码以嵌入到 bash 脚本中,那么您几乎肯定不希望 shell 替换——您希望代码以与未嵌入 bash 脚本时相同的方式运行,对吧?跨度>
一个完整的例子会很好。
Ricardo Cárdenes 下面的回答有一个更完整的例子,仅供参考:***.com/a/2189116/1157440【参考方案9】:
为什么需要使用-c
?这对我有用:
python << END
... code ...
END
不需要任何额外的东西。
【讨论】:
为了将输出收集到一个变量中,我做了ABC=$(python << END
... END)
并且成功了。
如果我们想与 python 通信一个来自 bash 脚本的字符串参数怎么办?
那么你需要-
,就像 Ned 的回答一样。参数将跟随破折号。
注意命名heredoc标记的方式。当它在您的示例中未引用时,shell 扩展将在 heredoc 字符串中发生。例如,如果您的 python 代码仅包含 print '$SHELL'
,则输出将是 /bin/bash
或您的 shell 恰好是什么。如果将第一行更改为python - <<'END'
,则输出将为$SHELL
。如果您要复制和粘贴现有代码以嵌入到 bash 脚本中,那么您几乎肯定不希望 shell 替换——您希望代码以与未嵌入 bash 脚本时相同的方式运行,对吧?跨度>
@user3342981 如果您将所有内容都放在一行中,就像看起来那样,那是行不通的:***.com/questions/18660798/…以上是关于在 bash 脚本中嵌入简短的 python 脚本的主要内容,如果未能解决你的问题,请参考以下文章