如何使用 Python shlex 解析 bash 数组?
How to parse bash array using Python shlex?
输入:
declare -a ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop" [1]="L *:9166:8.8.8.8:9100 # google")
期望的输出
我想得到这个输出:
{
'ForwardPort': [
'"L *:9102:10.0.1.8:9100 # remote laptop"',
'"L *:9166:8.8.8.8:9100 # google"'
]
}
尝试
我试着玩了一下shlex
,但是数组的解析很糟糕:
import shlex
line='ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop" [1]="L *:9166:8.8.8.8:9100 # google")'
lex=shlex.shlex(line)
list(lex)
['ForwardPort', '=', '(', '[', '0', ']', '=', '"L *:9102:10.0.1.8:9100 # remote laptop"', '[', '1', ']', '=', '"L *:9166:8.8.8.8:9100 # google"', ')']
问题
有没有办法自动将ForwardPort
的值解析成列表?
N.B.: 不要在家里重现这是一个糟糕的设计决定导致了这个复杂的问题:S
您可以在 bash 中打印出来:
#!/bin/bash
declare -a ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop" [1]="L *:9166:8.8.8.8:9100 # google")
res=$(python -c 'import json, sys; print(json.dumps({"ForwardPort": [v for v in sys.argv[1:]]}))' "${ForwardPort[@]}")
echo "$res"
给出:
{"ForwardPort": ["L *:9102:10.0.1.8:9100 # remote laptop", "L *:9166:8.8.8.8:9100 # google"]}
如果您将 bash 数组定义为 python 中的字符串,您可以尝试这种有点粗略的解析:
import re
line='ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop" [1]="L *:9166:8.8.8.8:9100 # google")'
name, arr = line.split('=(')
arr = arr[:-1] # removing the trailing ')'
lst = [item for item in re.split('\[\d+\]=', arr) if item]
dct = {name: lst}
print(dct)
从 Python 开始,并从那里启动 bash(实际上与 相反,它从 bash 启动 Python):
import subprocess
print_array_script=r'''
source "" || exit
declare -n arrayToPrint= || exit
printf '%s[=10=]' "${arrayToPrint[@]}"
'''
def bashArrayFromConfigFile(scriptName, arrayName):
return subprocess.Popen(['bash', '-c', print_array_script, '_', scriptName, arrayName],
stdout=subprocess.PIPE).communicate()[0].split('[=10=]')[:-1]
print(bashArrayFromConfigFile('file.txt', 'ForwardPort'))
使用如下创建的输入文件进行测试:
cat >file.txt <<'EOF'
declare -a ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop"
[1]="L *:9166:8.8.8.8:9100 # google")
EOF
...正确地作为输出发出:
['L *:9102:10.0.1.8:9100 # remote laptop', 'L *:9166:8.8.8.8:9100 # google']
输入:
declare -a ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop" [1]="L *:9166:8.8.8.8:9100 # google")
期望的输出
我想得到这个输出:
{
'ForwardPort': [
'"L *:9102:10.0.1.8:9100 # remote laptop"',
'"L *:9166:8.8.8.8:9100 # google"'
]
}
尝试
我试着玩了一下shlex
,但是数组的解析很糟糕:
import shlex
line='ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop" [1]="L *:9166:8.8.8.8:9100 # google")'
lex=shlex.shlex(line)
list(lex)
['ForwardPort', '=', '(', '[', '0', ']', '=', '"L *:9102:10.0.1.8:9100 # remote laptop"', '[', '1', ']', '=', '"L *:9166:8.8.8.8:9100 # google"', ')']
问题
有没有办法自动将ForwardPort
的值解析成列表?
N.B.: 不要在家里重现这是一个糟糕的设计决定导致了这个复杂的问题:S
您可以在 bash 中打印出来:
#!/bin/bash
declare -a ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop" [1]="L *:9166:8.8.8.8:9100 # google")
res=$(python -c 'import json, sys; print(json.dumps({"ForwardPort": [v for v in sys.argv[1:]]}))' "${ForwardPort[@]}")
echo "$res"
给出:
{"ForwardPort": ["L *:9102:10.0.1.8:9100 # remote laptop", "L *:9166:8.8.8.8:9100 # google"]}
如果您将 bash 数组定义为 python 中的字符串,您可以尝试这种有点粗略的解析:
import re
line='ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop" [1]="L *:9166:8.8.8.8:9100 # google")'
name, arr = line.split('=(')
arr = arr[:-1] # removing the trailing ')'
lst = [item for item in re.split('\[\d+\]=', arr) if item]
dct = {name: lst}
print(dct)
从 Python 开始,并从那里启动 bash(实际上与
import subprocess
print_array_script=r'''
source "" || exit
declare -n arrayToPrint= || exit
printf '%s[=10=]' "${arrayToPrint[@]}"
'''
def bashArrayFromConfigFile(scriptName, arrayName):
return subprocess.Popen(['bash', '-c', print_array_script, '_', scriptName, arrayName],
stdout=subprocess.PIPE).communicate()[0].split('[=10=]')[:-1]
print(bashArrayFromConfigFile('file.txt', 'ForwardPort'))
使用如下创建的输入文件进行测试:
cat >file.txt <<'EOF'
declare -a ForwardPort=([0]="L *:9102:10.0.1.8:9100 # remote laptop"
[1]="L *:9166:8.8.8.8:9100 # google")
EOF
...正确地作为输出发出:
['L *:9102:10.0.1.8:9100 # remote laptop', 'L *:9166:8.8.8.8:9100 # google']