我的python文件有以下两个变量:
week_date = "01/03/16-01/09/16"
cust_id = "12345"
我如何将其读入一个包含这两个变量的shell脚本?
我当前的shell脚本需要手动编辑“dt”和“id”。我想将python变量读入shell脚本,这样我就可以编辑我的python参数文件而不是那么多文件。
shell文件:
#!/bin/sh
dt="01/03/16-01/09/16"
cust_id="12345"
在一个新的python文件中,我可以导入参数python文件。
答案 0 :(得分:8)
考虑类似于以下内容:
#!/bin/bash
# ^^^^ NOT /bin/sh, which doesn't have process substitution available.
python_script='
import sys
d = {} # create a context for variables
exec(open(sys.argv[1], "r").read()) in d # execute the Python code in that context
for k in sys.argv[2:]:
print "%s\0" % str(d[k]).split("\0")[0] # ...and extract your strings NUL-delimited
'
read_python_vars() {
local python_file=$1; shift
local varname
for varname; do
IFS= read -r -d '' "${varname#*:}"
done < <(python -c "$python_script" "$python_file" "${@%%:*}")
}
然后您可以将其用作:
read_python_vars config.py week_date:dt cust_id:id
echo "Customer id is $id; date range is $dt"
...或者,如果您不想在阅读时重命名变量,只需:
read_python_vars config.py week_date cust_id
echo "Customer id is $cust_id; date range is $week_date"
优点:
sed
来处理原始字符串和常规字符串,以及单引号和三引号,而不是将其编入一个毛球!)或类似的方法,使用Python子进程中换行分隔的输出,这将正确处理str()
给出的表示没有您的shell脚本可以使用的NUL字符的任何对象。通过Python解释器运行内容也意味着您可以通过编程方式确定值 - 例如,您可能会有一些Python代码向您的版本控制系统询问相关内容的最后更改日期。
考虑这样的场景:
start_date = '01/03/16'
end_date = '01/09/16'
week_date = '%s-%s' % (start_date, end_date)
...使用Python解释器来解析Python意味着您不会限制人们将来如何更新/修改Python配置文件。
现在,让我们来谈谈警告:
import
文件作为Python中的模块一样)。不要使用它从您不信任的内容中提取配置。str()
表示包含NUL的对象溢出到其他赋值中,此代码在其第一个NUL处终止字符串。现在,我们来谈谈实施细节。
${@%%:*}
是$@
的扩展,用于修剪每个参数中的第一个:
之后的所有内容,从而仅将Python变量名称传递给解释器。同样,${varname#*:}
是一个扩展,可以修改传递给:
的变量名称中的第一个read
。见the bash-hackers page on parameter expansion。<(python ...)
是进程替换语法:<(...)
表达式求值为一个文件名,当读取该文件名时,将提供该命令的输出。使用< <(...)
重定向来自该文件的输出,从而使用该命令(第一个<
是重定向,而第二个是启动进程替换的<(
令牌的一部分)。使用此表单将输出转换为while read
循环可以避免BashFAQ #24 ("I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?")中提到的错误。 IFS= read -r -d ''
构造包含一系列组件,每个组件都使read
的行为更符合原始内容:
IFS
可防止从变量内容的末尾修剪空格。-r
可以防止read
本身消耗文字反斜杠,而不是在输出中表示。-d ''
将空字符串''
的第一个字符设置为记录分隔符。由于C字符串是NUL终止的,而shell使用C字符串,因此该字符是NUL。这可以确保变量的内容可以包含任何非NUL值,包括文字换行符。有关从bash中的字符串中读取面向记录的数据的过程的更多信息,请参阅BashFAQ #001 ("How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?")。
答案 1 :(得分:2)
其他答案提供了一种方法来完全按照你的要求行事,但我认为这个想法有点疯狂。有一种更简单的方法来满足两个脚本 - 将这些变量移动到配置文件中。您甚至可以保留简单的分配格式。
创建配置本身:( ini-style)
jlayeredpane.add(jbutton, JLayeredPane.DEFAULT_LAYER);
在python中:
dt="01/03/16-01/09/16"
cust_id="12345"
在bash中:
config_vars = {}
with open('the/file/path', 'r') as f:
for line in f:
if '=' in line:
k,v = line.split('=', 1)
config_vars[k] = v
week_date = config_vars['dt']
cust_id = config_vars['cust_id']
你不再需要做疯狂的源解析了。或者你可以只使用json作为配置文件,然后在python中使用source "the/file/path"
模块,在shell中使用json
进行解析。
答案 2 :(得分:0)
我会做这样的事情。你可能想稍微修改它以进行微小的更改以包含/排除引号,因为我没有为你的场景测试过它:
#!/bin/sh
exec <$python_filename
while read line
do
match=`echo $line|grep "week_date ="`
if [ $? -eq 0 ]; then
dt=`echo $line|cut -d '"' -f 2`
fi
match=`echo $line|grep "cust_id ="`
if [ $? -eq 0 ]; then
cust_id=`echo $line|cut -d '"' -f 2`
fi
done