shell 脚本中的混合代码。共享变量

shell 脚本中的混合代码。共享变量

这个答案讨论如何从终端中的命令行运行多行 Python 代码片段。我注意到答案在 shell 脚本中效果很好,即使有嵌套缩进,这非常好,例如

#!/bin/bash
some_text="Hello world"
echo $some_text

cat <<EOF | python -
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF

印刷:

0 
hello
hello
1
hello
hello
2
hello
hello

但是,我很难在 shell 脚本和 Python 代码片段之间共享变量。

  1. 如何收集bash脚本中python下标的输出? (例如,在诸如 之类的变量中$output)。

  2. 如何将 bash 变量(例如$some_text)传递给 Python 脚本?

答案1

获取 Python 变量

由于(当EOF标记未加引号时)变量替换发生在文本从定界符传递到python的标准输入之前,因此您可以将变量直接扔到脚本中。

python - <<EOF
some_text = "$some_text"
EOF

如果some_text是的话test,Python 就会看到some_text = "test"。但请注意,它可以被视为代码注入漏洞。例如,如果some_textwas ,python 会看到:"; import os; os.system("evil-command"); x = "

some_text = ""; import os; os.system("evil-command"); x = ""

并运行那个邪恶的命令。

如果您希望能够将 Python 代码直接拉入脚本而不进行任何修改,您可以导出变量。

export some_text

并用于os.environ检索它。

some_text = os.environ['some_text']

这是一种更明智/更安全的方法。


从 Python 获取输出

您可以使用命令替换来收集脚本的输出。

output=$(
python - <<EOF
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)

(请注意,所有尾随换行符都将被删除)

答案2

您的方法的问题是嵌入式 python 脚本不再能够访问原始的标准输入(因为它的标准输入是...本身)。

如果这是一个问题,你可以写:

python -c '
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
'

或者如果 python 脚本可能包含单引号:

python -c "$(cat << 'EOF'
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)"

或者:

python <(cat << 'EOF'
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)

答案3

使用破折号作为文件名:

ruby - a b <<'END'
puts ARGV.join(",")
END

python - a b <<'END'
import sys
print ",".join(sys.argv[1:])
END

我不知道sys.argv[1:]在 Python 中执行此操作是否正确。对于 -e / -c 您可以使用 -- 指定参数结尾:

set -- -a -b -c
ruby -e 'puts ARGV.join(",")' -- "$@"
python -c 'import sys; print ",".join(sys.argv[2:])' -- "$@"

捕获输出并重定向 STDERR:

x=$(ruby <<'END' 2> /dev/null
puts "a"
abort "b"
END
)

答案4

1)您可以在 python 中将变量赋值写入文件,然后在 bash 脚本中获取该文件。

2)由于您的单词(EOF)没有被引用,因此here-document的所有行都受到参数扩展。您可以使用它将内容传递给 python 脚本。

相关内容