명령 출력에서 ​​값을 추출하고 해당 값을 후속 명령의 매개변수로 사용합니다.

명령 출력에서 ​​값을 추출하고 해당 값을 후속 명령의 매개변수로 사용합니다.

안녕하세요.

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 명령. 이제 라인("패턴 공간")은 다음과 같습니다: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>먼저, stackexchange는 내가 스팸을 보내고 있다고 생각하여 게시를 허용하지 않기 때문에 명령에 있는 URL을 대체해야 했습니다 .

좋습니다. 여기에는 두 가지 질문이 있습니다.

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) 전체 JSON 출력에서 ​​"token_of_token"만 분리하려면 어떻게 해야 합니까?

일부 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출력에 여러 개의 토큰 라인이 있는 경우를 대비하여 첫 번째 토큰 라인만 사용됩니다 .

이 애플리케이션이 중요하다면 이는 매우 강력한 솔루션이 아니라는 점을 알아야 합니다. 그렇다면 반환 코드를 확인하고 첫 번째 컬 명령의 출력에 대한 보다 광범위한 유효성 검사를 수행하여 예상치 못한 결과가 발생하지 않도록 해야 합니다. 하지만 그러려면 더 큰 스크립트가 필요하며 이 질문의 범위를 벗어납니다.

관련 정보