Нужно изменить код Perl на чистой оболочке. Разбор файла и изменение ENV - PullRequest
0 голосов
/ 26 июня 2019

Я хочу изменить этот кусок кода: $(perl -p -e 's/\$(\w+)/("$ENV{$1}")/eg' < file_with_html)

и делать разбор и замену без perl file_with_html: содержит HTML-шаблон, например

      <th class='xtr-0-0'>Version name</th>
      <td class='xtr-0-1'>$RELEASE_TAG</td>
    </tr>
    <tr class='xtr-1'>
      <th class='xtr-1-0'>Link</th>
      <td class='xtr-1-1'>$RELEASE_URL</td>...

Мне нужно изменить все $ (\ w +) на ENV с тем же именем и отправьте этот "разобранный" шаблон в запрос POST. Как я могу сделать это с помощью grep / sed / awk / etc?

UPD1: Отправляю POST с curl

Полный текст, который генерирует новую страницу в Confluence:

newPageTemplate=$(perl -p -e 's/\$(\w+)/("$ENV{$1}")/eg' < $CONFLUENCE_PAGE_TEMPLATE)

newPageContent="{
    \"type\": \"page\",
    \"title\": \"$CONFLUENCE_PAGE_TITLE\",
    \"ancestors\": [
        {
            \"id\": \"$CONFLUENCE_PARENTPAGE_ID\"
        }
    ],
    \"space\": {
        \"key\": \"$CONFLUENCE_SPACE\"
    },
    \"body\": {
        \"storage\": {
            \"value\": \"$(echo ${newPageTemplate})\",
            \"representation\": \"storage\"
        }
    }
}"
curl --request POST \
--url $CONFLUENCE_API_URL \
--header "authorization: Basic $JIRA_TOKEN" \
--header "content-type: application/json" \
--data "$newPageContent"

Ответы [ 2 ]

1 голос
/ 28 июня 2019

Оригинальный Perl намного проще, но, вероятно, это можно сделать в awk.

Perl \w соответствует чуть более чем [0-9a-zA-Z_] (см .: https://metacpan.org/pod/perlrecharclass#Word-characters), но я предполагаю, что это все, что появится в имени переменной среды (которое также не может начинаться с цифры).

POSIX AWK

awk '
    {
        n = split( $0, f, /[^$0-9a-zA-Z_]+/ )
        for ( i=1; i<=n; i++ ) {
            v = f[i]
            if ( v ~ /^[$][a-zA-Z_]/ ) {
                sub( /^[$]/, "", v )
                sub( "[$]"v, ENVIRON[v] )
            }
        }
    }
    1
' file_with_html
  • split извлекает ссылки на потенциальные переменные среды
  • v ~ /.../ соответствует только действительным
  • первый sub удаляет ведущий $
  • секунда sub заменяет $ соответствующим экранированием и заменяет ссылку на переменную значением (если есть)
  • 1 печатает каждую строку

Предупреждение: В приведенном выше коде есть небольшая ошибка. В патологическом случае, когда строке требуется несколько подстановок, а значение единицы выглядит как ссылка на последующую, потому что подстановки не происходят одновременно, неправильная часть строки будет изменена. Например. Если A='$B'; B='x'; и строка содержит: .. $A .. $B .., вывод будет .. x .. $B .., а не .. $B .. x ...

GNU GAWK

Ошибка может быть исправлена, если используются расширения gawk. Например, с patsplit:

gawk '
   {
      if (n = patsplit($0, f, "[$][a-zA-Z_][0-9a-zA-Z_]*", s)) {
         printf "%s", s[0]
         for ( i=1; i<=n; i++ ) {
            sub( /^[$]/, "", f[i] )
            printf "%s%s", ENVIRON[ f[i] ], s[i]
         }
         printf "\n"
      }
      else print
   }
' file_with_html
0 голосов
/ 27 июня 2019

Добро пожаловать в переполнение стека.

Мне нужно изменить все $ (\ w +) для ENV с тем же именем.Как я могу сделать это с помощью grep / sed / awk / etc?

Во-первых, grep, sed и awk не являются "чистой оболочкой".Это команды, установленные в системе, как и perl.Если вы можете установить perl, я рекомендую его;это ужасно полезно.Если нет, то ваш следующий лучший подход - копирование исходных файлов на компьютер, на котором вы можете установить perl, и запуск процесса как есть, так как конечным результатом является POST-результаты обратно в Confluence.(то есть, вы можете POST из вне системы).

Но, если вы действительно не можете использовать perl, конечно, есть способ сделать это с другими инструментами обработки текста, такими как grepsed и awk.

Во-вторых, что вы пробовали до сих пор?Stack Overflow работает лучше всего, когда вы показываете нам, что вы уже сделали, что работает, и как это не работает.Это помогает людям сфокусировать свои ответы в соответствии с вашей конкретной проблемой и с учетом вашего текущего понимания.

В-третьих, вот сценарий, который может вам помочь.Опять же, я не знаю, сколько bash вы знаете, так что это может быть немного неясным.Это также, конечно, не единственный способ сделать это, и, вероятно, не самый лучший.Я настоятельно рекомендую проверить это, запустив его на нескольких образцах страниц и проверив выходные данные перед тем, как POST'ing это;инструменты типа diff или vimdiff очень помогут здесь.Затем, даже когда вы готовы на самом деле отправить результаты, начните медленно с подмножества и проверьте результаты, прежде чем открывать пожарный шланг.


ПРЕДУПРЕЖДЕНИЕ: приведенный ниже скрипт не работает в обычных условиях

Как отмечает @jhnc в комментариях, команда sed завершится неудачно, если текст замены содержит символы, которые являются метасимволами замены для sed (например, '/' в URL),Есть способ компенсировать дальнейшую логику сценария, но ИМХО по этому пути лежит безумие.

Моя рекомендация, если perl не может быть установлена ​​на целевой машине, - это мой "следующий лучший подход", который яупомянутое выше: скопируйте входные данные на компьютер, на котором вы можете запустить perl и оттуда запустить преобразование и POST обратно в Confluence.

Но также посмотритена ответ от @jhnc, который предлагает решение, которое позволяет избежать этой слабости в моем.

(я помещаю это предупреждение вместо удаления своего ответа из-за более простых решений, приведенных выше, и вВ случае, если этот подход послужит основой для того, кто хочет улучшить его.)

ИСПОЛЬЗУЙТЕ НИЖЕ ПОДХОД С БОЛЬШИМ СДЕЛКОМ ОСТОРОЖНО


replace-env-params.sh

#!/bin/bash

while IFS= read -r LINE; do

    MATCH=$(echo "$LINE" | grep -E '\$[a-zA-Z0-9_]+')
    if [[ ! -z "$MATCH" ]]; then
        ENVPARAM=$(echo "$LINE" | sed 's/^.*\$\([a-zA-Z0-9_]*\).*$/\1/')

        ENVVAL="$ENVPARAM"
        REPLACE="${!ENVVAL}"

        LINE=$(echo "$LINE" | sed "s/\$[a-zA-Z0-9_]*/$REPLACE/")
    fi

    echo "$LINE"

done < $1

cat somehtml

      <th class='xtr-0-0'>Version name</th>
      <td class='xtr-0-1'>$RELEASE_TAG</td>
    </tr>
    <tr class='xtr-1'>
      <th class='xtr-1-0'>Link</th>
      <td class='xtr-1-1'>$RELEASE_URL</td>

тестирование ...

export RELEASE_TAG=11111111
export RELEASE_URL=22222222

./replace-env-params.sh somehtml

      <th class='xtr-0-0'>Version name</th>
      <td class='xtr-0-1'>11111111</td>
    </tr>
    <tr class='xtr-1'>
      <th class='xtr-1-0'>Link</th>
      <td class='xtr-1-1'>22222222</td>

Таким образом, вы можете заменить:

newPageTemplate=$(perl -p -e 's/\$(\w+)/("$ENV{$1}")/eg' < $CONFLUENCE_PAGE_TEMPLATE)

на

newPageTemplate=$(./replace-env-params.sh $CONFLUENCE_PAGE_TEMPLATE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...