Токенизация строки в bash без использования перенаправления - PullRequest
0 голосов
/ 08 января 2020

Ну, в моем скрипте я использую простую строку для токенизации:

IFS=';' read -ra ALL_ADDR <<< "${SERVER}"

Однако, когда я запускаю этот скрипт в контейнере busybox (alpine) linux docker, он спотыкается вокруг строки выше , line 43: syntax error: unexpected redirection

Я понимаю, что это потому, что скрипт запускается не Bash, а Ash, который не имеет параметра перенаправления <<<. Как я могу преобразовать вышеуказанную строку в код, который работает аналогично всем популярным сценариям оболочки. (В основном Bash, A sh и Da sh)?

для полноты, переменная имеет вид:

SERVER="/api/v1:127.0.0.1:1337;/api/v2:127.0.0.1:1338"
IFS=';' read -ra ALL_ADDR <<< "${SERVER}"
for i in "${ALL_ADDR[@]}"; do
    IFS=':' read -ra ADDR <<< "${i}"
    PROXY=${ADDR[0]}
    IPADDR=${ADDR[1]}
    PORT=${ADDR[2]}
    LOC_STRING="${LOC_STRING}\tlocation ${PROXY} {\n\t\tproxy_pass http://${IPADDR}:${PORT}\n\t}\n"
done
LOC_STRING=${LOC_STRING//\//\\\/}

#"insert" above generated lines into a site config for nginx
sed -e "0,/^\s*location/{s/^\s*location/${LOC_STRING}\n&/}" 'portal' > "../sites-enabled/portal"

Ответы [ 3 ]

0 голосов
/ 08 января 2020

Поскольку это просто вопрос о следующей строке, я просто попутно упомяну, что вам не следует использовать массивы в сценарии, предназначенном для переносимости. Игнорируя эту проблему на данный момент, вы всегда можете заменить эту строку на heredo c:

IFS=';' read -ra ALL_ADDR << EOF
${SERVER}
EOF

Обратите внимание, что вы действительно не должны кричать, и это было бы лучше написать:

IFS=';' read -ra all_addr << EOF
${server}
EOF
0 голосов
/ 09 января 2020

Возможно, я не отвечаю прямо на ваш вопрос, но как насчет решения sed:

SERVER="/api/v1:127.0.0.1:1337;/api/v2:127.0.0.1:1338"
LOC_STRING=$(echo "$SERVER" | tr ';' '\n' | sed -e 's#\([^:]*\):\([^:]*\):\([^:]*\)#\tlocation \1 {\n\t\tproxy_pass http://\2:\3\n\t}#' -e 's#/#\\/#g')

Вывод echo "$LOC_STRING":

    location \/api\/v1 {
        proxy_pass http:\/\/127.0.0.1:1337
    }
    location \/api\/v2 {
        proxy_pass http:\/\/127.0.0.1:1338
    }

Обратите внимание, что слово \n в двойных кавычках декодируется как символ новой строки в ash, а остается как в bash. В зависимости от ваших требований может потребоваться небольшая настройка.

0 голосов
/ 08 января 2020

Похоже, вам не нужно его токенизировать. Просто сгенерируйте полученную строку.

Ниже я сначала подставляю каждый : или ; на новую строку. Затем с xargs я читаю 3 переменные одновременно и перехожу к printf формату. sed 's@/@\\/@g' делает то же самое, что и LOC_STRING=${LOC_STRING//\//\\\/}.

SERVER="/api/v1:127.0.0.1:1337;/api/v2:127.0.0.1:1338"
LOC_STRING=$(
    printf "%s\n" "$SERVER"  |
    tr ':;' '\n\n' |
    xargs -d$'\n' -n3 printf '\tlocation %s {\\n\t\tproxy_pass http://%s:%s\\n\t}\\n' |
    sed 's@/@\\/@g'
)

echo "$LOC_STRING"

:

    location \/api\/v1 {\n      proxy_pass http:\/\/127.0.0.1:1337\n  }\n location \/api\/v2 {\n      proxy_pass http:\/\/127.0.0.1:1338\n  }\n

Чтобы "токенизировать" его, проще всего вставить новую строку вместо разделителя, и прочитайте это как разделенный новой строкой поток. Будут проблемы, если в строке есть новая строка, но, судя по IFS=';' read -ra ALL_ADDR <<< "${SERVER}", в SERVER нет новых строк или вас интересует только первая строка. Так похоже - замените ; и : на новую строку. Тогда только прочитайте 3 пункта за один раз. Используйте << для перенаправления чего-либо в оболочке posix.

tmp=$(printf "%s\n" "$SERVER" | tr ';:' '\n\n')
while IFS= read -r PROXY &&
        IFS= read -r IPADDR &&
        IFS= read -r POST; do
    LOC_STRING="${LOC_STRING}\tlocation ${PROXY} {\n\t\tproxy_pass http://${IPADDR}:${PORT}\n\t}\n"
done <<EOF
$tmp
EOF
LOC_STRING=${LOC_STRING//\//\\\/}

Примечание: по договоренности переменные верхнего регистра используются для переменных, которые будут export ed. Для локальных переменных в скрипте используйте строчные переменные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...