Как разобрать массив bash с помощью Python shlex? - PullRequest
0 голосов
/ 15 октября 2018

Ввод:

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 в списке?

Примечание: не воспроизводите дома, это было плохое дизайнерское решение, которое привело к этой запутанной проблеме: S

Ответы [ 2 ]

0 голосов
/ 16 октября 2018

Начиная с 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']
0 голосов
/ 15 октября 2018

вы можете распечатать это в 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)
...