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
в списке?
NB: Не воспроизводите дома, это было плохое дизайнерское решение, которое привело к этой запутанной проблеме: 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)
printf '%s\0' "${array[@]}"
, и тогда ваш код Python может просто разделиться на NUL. Но, как и этот ответ, это зависит от того, чтобы на самом деле вызывать bash для выполнения работы.
Начиная с Python и запуская bash оттуда (эффективно, как обратный ответ hiro, который запускает Python из bash):
import subprocess
print_array_script=r'''
source "$1" || exit
declare -n arrayToPrint=$2 || exit
printf '%s\0' "${arrayToPrint[@]}"
'''
def bashArrayFromConfigFile(scriptName, arrayName):
return subprocess.Popen(['bash', '-c', print_array_script, '_', scriptName, arrayName],
stdout=subprocess.PIPE).communicate()[0].split('\0')[:-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']
ForwardPort
? Кажется, вы пересекаете два разных языка. Есть ли какая-то причина, почему ваш ForwardPort находится в формате массива bash?shlex.shlex
- это лексер, он вернет список токенов, который вы можете проанализировать,