Извлечь значение из вывода команды и использовать его в качестве параметра для последующей команды.

Извлечь значение из вывода команды и использовать его в качестве параметра для последующей команды.

Привет, я пытаюсь

curl -v --request POST https://example.com --data-urlencode "username=usr]” --data-urlencode "password=[pass]”

передайте вывод в [TOKEN]поле здесь:

curl -D - --request POST https://example.com --data-urlencode token=[TOKEN]

Однако я не знаком с JSON, так как мой вывод для первой команды выглядит так:

{
    "token": "value_of_token"
}

Как бы мне просто взять "value_of_token"и заставить это быть [TOKEN]?

решение1

Чтобы наиболее эффективно использовать только value_of_tokenвывод команды curl, передайте вывод в одну sedкоманду (редактор потока). Используйте подстановку команд $()для сохранения вывода в переменной оболочки:

token=$(curl ... | sed -n '/ *"token": *"/ { s///; s/".*//; p; }')

Затем вы можете сослаться на переменную tokenкак на параметр второй curlкоманды:

curl ... token="$token"

Пояснение к sedкоманде:

sed -n '/ *"token" *: *"/ { s///; s/".*//; p; q; }'
  • -nопция sedговоритнетраспечатать каждую входную строку

  • / *"token" *: *"/обращается к строке, содержащей значение. Этот шаблон (регулярное выражение) соответствует всему началу строки, вплоть до первой двойной кавычки, ограничивающей значение токена, включая ее.

  • {начать командный блок, который будет применен к адресованной строке.

  • s///;команда sed для удаления того, что было ранее сопоставлено (в части адреса). Строка ("pattern space") теперь выглядит так:value_of_token"

  • s/".*//Команда sed для удаления оставшейся двойной кавычки ( ") и всего, что находится после нее.

  • pКоманда sed для печати текущей (отредактированной) строки (в sedтерминологии «шаблонное пространство»).

  • qНемедленно завершить работу скрипта sed без дальнейшей обработки ввода.

  • '}' завершает командный блок.

Например,

$ echo '
{                          
    "token": "value_of_token"
}
' | sed -n '/ *"token" *: *"/ { s///; s/".*//; p; }'
value_of_token
$

Этот метод гораздо эффективнее, чем объединение 4 других команд для достижения того же результата. Эта sedкоманда предполагает, что во входных данных JSON нет символов табуляции. Если табуляция есть, sedкоманду необходимо будет изменить.

решение2

Во-первых, обратите внимание, что мне пришлось заменить URL-адрес, указанный в ваших командах, <URL>потому что StackExchange посчитал, что я рассылаю спам, и не разрешил мне публиковать сообщения.

Хорошо, у вас есть два вопроса:

1) Как взять вывод одной команды и сделать его аргументом другой команды?

ответ: Наиболее каноническим методом будет использование подстановки команд оболочки, путем замены вашего аргумента во второй команде следующим образом $( <first command> ):

curl -D - --request POST <URL> --data-urlencode token=$( curl -v --request POST <URL> --data-urlencode "username=usr]” --data-urlencode "password=[pass]” )

Однако для удобства чтения вам действительно следует сделать это в отдельных строках, сохранив вывод первой команды и повторно используя его следующим образом:

token=$( curl -v --request POST <URL> --data-urlencode "username=usr]” --data-urlencode "password=[pass]” )
curl -D - --request POST <URL> --data-urlencode token="$token"

Кроме того, для полноты картины и поскольку вы конкретно спрашивали, как «передавать по конвейеру», вы можете использовать команду xargs вместо подстановки команд оболочки:

curl -v --request POST <URL> --data-urlencode "username=usr]” --data-urlencode "password=[pass]” | xargs "curl -D - --request POST <URL> --data-urlencode token="{}

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

2) Как можно выделить только «value_of_token» из всего вывода JSON?

Не вдаваясь в подробности JSON API, простая конвейеризация grep, head и cut должна справиться с этой задачей:

token=$( curl -v --request POST <URL> --data-urlencode "username=usr]” --data-urlencode "password=[pass]” ) | grep '"token":' | head -1 | cut -d ':' -f 2 | cut -d '"' -f 2
curl -D - --request POST <URL> --data-urlencode token="$token"

Обратите внимание, что это head -1сделано только на тот случай, если на выходе окажется несколько строк токенов; в этом случае будет использоваться только первая.

Вы должны знать, что это не очень надежное решение, если это приложение важно. Если это так, вам действительно следует проверить код возврата и провести более обширную проверку вывода первой команды curl, чтобы не получить неожиданных результатов; но это потребует более крупного скрипта и выходит за рамки этого вопроса.

Связанный контент