Sử dụng curl POST với các biến được xác định trong các hàm bash script


175

Khi tôi lặp lại, tôi nhận được cái này, nó chạy khi tôi nhập nó vào thiết bị đầu cuối

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data '{"account":{"email":"akdgdtk@test.com","screenName":"akdgdtk","type":"NIKE","passwordSettings":{"password":"Starwars1","passwordConfirm":"Starwars1"}},"firstName":"Test","lastName":"User","middleName":"ObiWan","locale":"en_US","registrationSiteId":"520","receiveEmail":"false","dateOfBirth":"1984-12-25","mobileNumber":"9175555555","gender":"male","fuelActivationDate":"2010-10-22","postalCode":"10022","country":"US","city":"Beverton","state":"OR","bio":"This is a test user","jpFirstNameKana":"unsure","jpLastNameKana":"ofthis","height":"80","weight":"175","distanceUnit":"MILES","weightUnit":"POUNDS","heightUnit":"FT/INCHES"}' https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx

Nhưng khi chạy trong tệp bash script, tôi gặp lỗi này

curl: (6) Could not resolve host: application; nodename nor servname provided, or not known
curl: (6) Could not resolve host: is; nodename nor servname provided, or not known
curl: (6) Could not resolve host: a; nodename nor servname provided, or not known
curl: (6) Could not resolve host: test; nodename nor servname provided, or not known
curl: (3) [globbing] unmatched close brace/bracket at pos 158

đây là mã trong tập tin

curl -i \
-H '"'Accept: application/json'"' \
-H '"'Content-Type:application/json'"' \
-X POST --data "'"'{"account":{"email":"'$email'","screenName":"'$screenName'","type":"'$theType'","passwordSettings":{"password":"'$password'","passwordConfirm":"'$password'"}},"firstName":"'$firstName'","lastName":"'$lastName'","middleName":"'$middleName'","locale":"'$locale'","registrationSiteId":"'$registrationSiteId'","receiveEmail":"'$receiveEmail'","dateOfBirth":"'$dob'","mobileNumber":"'$mobileNumber'","gender":"'$gender'","fuelActivationDate":"'$fuelActivationDate'","postalCode":"'$postalCode'","country":"'$country'","city":"'$city'","state":"'$state'","bio":"'$bio'","jpFirstNameKana":"'$jpFirstNameKana'","jpLastNameKana":"'$jpLastNameKana'","height":"'$height'","weight":"'$weight'","distanceUnit":"MILES","weightUnit":"POUNDS","heightUnit":"FT/INCHES"}'"'" "https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx"

Tôi cho rằng có vấn đề với dấu ngoặc kép của tôi, nhưng tôi đã chơi với họ rất nhiều và tôi đã gặp phải lỗi tương tự. Tất cả các biến được xác định với các chức năng khác nhau trong tập lệnh thực tế

Câu trả lời:


273

Bạn không cần phải vượt qua các trích dẫn kèm theo các tiêu đề tùy chỉnh để cuộn tròn. Ngoài ra, các biến của bạn ở giữa datađối số nên được trích dẫn.

Đầu tiên, viết một hàm tạo dữ liệu bài viết của tập lệnh của bạn. Điều này giúp bạn tránh khỏi tất cả các loại đau đầu liên quan đến trích dẫn shell và giúp đọc một đoạn mã dễ dàng hơn so với việc cung cấp dữ liệu bài đăng trên dòng gọi của curl như trong nỗ lực của bạn:

generate_post_data()
{
  cat <<EOF
{
  "account": {
    "email": "$email",
    "screenName": "$screenName",
    "type": "$theType",
    "passwordSettings": {
      "password": "$password",
      "passwordConfirm": "$password"
    }
  },
  "firstName": "$firstName",
  "lastName": "$lastName",
  "middleName": "$middleName",
  "locale": "$locale",
  "registrationSiteId": "$registrationSiteId",
  "receiveEmail": "$receiveEmail",
  "dateOfBirth": "$dob",
  "mobileNumber": "$mobileNumber",
  "gender": "$gender",
  "fuelActivationDate": "$fuelActivationDate",
  "postalCode": "$postalCode",
  "country": "$country",
  "city": "$city",
  "state": "$state",
  "bio": "$bio",
  "jpFirstNameKana": "$jpFirstNameKana",
  "jpLastNameKana": "$jpLastNameKana",
  "height": "$height",
  "weight": "$weight",
  "distanceUnit": "MILES",
  "weightUnit": "POUNDS",
  "heightUnit": "FT/INCHES"
}
EOF
}

Sau đó, thật dễ dàng để sử dụng chức năng đó trong việc gọi curl:

curl -i \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
-X POST --data "$(generate_post_data)" "https://xxx:xxxxx@xxxx-www.xxxxx.com/xxxxx/xxxx/xxxx"

Điều này cho biết, đây là một vài làm rõ về quy tắc trích dẫn shell:

Các dấu ngoặc kép trong các -Hđối số (như trong -H "foo bar") nói với bash để giữ những gì bên trong dưới dạng một đối số (ngay cả khi nó chứa khoảng trắng).

Các trích dẫn đơn trong --datađối số (như trong --data 'foo bar') cũng làm như vậy, ngoại trừ chúng chuyển tất cả nguyên văn văn bản (bao gồm các ký tự trích dẫn kép và ký hiệu đô la).

Để chèn một biến vào giữa một văn bản được trích dẫn, bạn phải kết thúc một trích dẫn, sau đó nối với biến trích dẫn kép và mở lại trích dẫn đơn để tiếp tục văn bản : 'foo bar'"$variable"'more foo'.


9
"'" $ <tên biến> "'" đã giải quyết vấn đề của tôi khi tôi không cần trích dẫn. Cảm ơn.
Usman

1
Giải pháp này hoạt động nhưng tôi nghĩ bạn có thể phát ra các trích dẫn kép bổ sung xung quanh biến. Vì vậy, thay vì điều này: --data '{"tài khoản": {"email": "'" $ email "'"}}' bạn có thể làm điều này: --data '{"tài khoản": {"email": " '$ email' "}} '
xoắn vào

3
Không hoạt động khi có khoảng trắng sau EOF thứ hai : EOF . Sau khi loại bỏ nó mọi thứ đều ổn.
Klaas

2
@dbreaux Điều đó phụ thuộc vào nơi bạn chạy lệnh curl. Nếu lệnh nằm trong một tập lệnh, bạn chỉ cần xác định hàm ở bất cứ đâu phía trên nó trong cùng tập lệnh đó. Nếu bạn đang chạy curl trực tiếp từ dòng lệnh, bạn có một số tùy chọn, một trong số đó là nhập hàm trong một tệp mới và sau đó tại dòng lệnh chạy source my_new_fileđể xác định hàm trong môi trường hiện tại của bạn. Sau đó, bạn có thể chạy lệnh curl như được chỉ định.
Ngài Hd

2
@slashdottir Đó là một tính năng bash có tên Here Documents. Bạn có thể đọc về nó chi tiết hơn tại liên kết này - đặc biệt, hãy xem Ví dụ 19-5. Cũng đã có một câu hỏi đầy đủ về nó ở đây trên SO.
Ngài Việt Nam

103

Giải pháp được thử nghiệm với https://httpbin.org/ và tập lệnh bash nội tuyến
1. Đối với các biến không có khoảng trắng trong đó, tức là 1:
Chỉ cần thêm 'trước và sau $variablekhi thay thế chuỗi mong muốn

for i in {1..3}; do \
  curl -X POST -H "Content-Type: application/json" -d \
    '{"number":"'$i'"}' "https://httpbin.org/post"; \
done

2. Đối với đầu vào có khoảng trắng:
Gói biến với bổ sung "tức là "el a":

declare -a arr=("el a" "el b" "el c"); for i in "${arr[@]}"; do \
  curl -X POST -H "Content-Type: application/json" -d \
    '{"elem":"'"$i"'"}' "https://httpbin.org/post"; \
done

Wow hoạt động :)


1
Không hoạt động khi khi $ichứa không gian. :(
Vasyl Boroviak

Bạn có thể gửi một ví dụ?
pbaranski

1
Chắc chắn rồi. i="a b"thay vì vòng lặp
Vasyl Boroviak

5
Tôi thấy rằng câu trả lời được chấp nhận và bình chọn thứ hai không hoạt động /bin/sh. Tuy nhiên, câu trả lời này đã lừa Và nó đơn giản hơn nhiều so với các câu trả lời khác. Cảm ơn bạn rất nhiều! Tôi đã chỉnh sửa câu trả lời của bạn với một số định dạng gói dòng đẹp hơn. Nếu không, thật khó để nhận ra sự sáng chói. Chúc mừng người bạn đời
Vasyl Boroviak

1
Cảm ơn rất nhiều @pbaranski bạn đã tiết kiệm rất nhiều thời gian của tôi
sudhir tataraju

32

Curl có thể đăng dữ liệu nhị phân từ một tệp vì vậy tôi đã sử dụng thay thế quy trình và tận dụng các mô tả tệp bất cứ khi nào tôi cần đăng một cái gì đó khó chịu với curl và vẫn muốn truy cập vào các vars trong shell hiện tại. Cái gì đó như:

curl "http://localhost:8080" \
-H "Accept: application/json" \
-H "Content-Type:application/json" \
--data @<(cat <<EOF
{
  "me": "$USER",
  "something": $(date +%s)
  }
EOF
)

Điều này trông giống như --data @/dev/fd/<some number>chỉ được xử lý như một tập tin bình thường. Dù sao, nếu bạn muốn thấy nó hoạt động cục bộ, chỉ cần chạy nc -l 8080đầu tiên và trong một lớp vỏ khác bắn ra lệnh trên. Bạn sẽ thấy một cái gì đó như:

POST / HTTP/1.1
Host: localhost:8080
User-Agent: curl/7.43.0
Accept: application/json
Content-Type:application/json
Content-Length: 43

{  "me": "username",  "something": 1465057519  }

Như bạn có thể thấy, bạn có thể gọi subshells và whatnot cũng như vars tham chiếu trong heredoc. Hạnh phúc hack hy vọng điều này sẽ giúp với '"'"'""""'''""''.


2
Câu trả lời khác không có tác dụng với tôi khi tôi đang cố gắng gọi nó trong một cảnh báo từ Zabbix. Điều này giải quyết nó hoàn hảo và sạch sẽ hơn.
0rkan

Nhưng nếu bạn đặt mã trong hàm bash: myFunction () {....} thì sao?
Hanynowsky

1
Cần lưu ý rằng công thức này chỉ hoạt động nếu tập lệnh được sao chép nguyên văn (nghĩa là không định dạng lại EOF, dấu ngoặc nhọn, v.v.)
Vader B

9

Một vài năm muộn nhưng điều này có thể giúp đỡ ai đó nếu bạn đang sử dụng thay thế eval hoặc backtick:

postDataJson="{\"guid\":\"$guid\",\"auth_token\":\"$token\"}"

Sử dụng sed để trích dẫn trích dẫn từ đầu và cuối phản hồi

$(curl --silent -H "Content-Type: application/json" https://${target_host}/runs/get-work -d ${postDataJson} | sed -e 's/^"//' -e 's/"$//')

4
  • thông tin từ Ngài Athos hoạt động hoàn hảo !!

Đây là cách tôi phải sử dụng nó trong tập lệnh curl của mình cho couchDB. Nó thực sự giúp ích rất nhiều. Cảm ơn!

bin/curl -X PUT "db_domain_name_:5984/_config/vhosts/$1.couchdb" -d '"/'"$1"'/"' --user "admin:*****"

3

Đây là những gì thực sự làm việc cho tôi, sau khi hướng dẫn từ câu trả lời ở đây:

export BASH_VARIABLE="[1,2,3]"
curl http://localhost:8080/path -d "$(cat <<EOF
{
  "name": $BASH_VARIABLE,
  "something": [
    "value1",
    "value2",
    "value3"
  ]
}
EOF
)" -H 'Content-Type: application/json'

2

Các câu trả lời hiện tại chỉ ra rằng curl có thể đăng dữ liệu từ một tệp và sử dụng heredocs để tránh trích dẫn quá mức thoát và rõ ràng phá vỡ JSON ra các dòng mới. Tuy nhiên, không cần xác định chức năng hoặc bắt đầu ra từ cat, vì curl có thể đăng dữ liệu từ đầu vào tiêu chuẩn. Tôi thấy hình thức này rất dễ đọc:

curl -X POST -H 'Content-Type:application/json' --data '$@-' ${API_URL} << EOF
{
  "account": {
    "email": "$email",
    "screenName": "$screenName",
    "type": "$theType",
    "passwordSettings": {
      "password": "$password",
      "passwordConfirm": "$password"
    }
  },
  "firstName": "$firstName",
  "lastName": "$lastName",
  "middleName": "$middleName",
  "locale": "$locale",
  "registrationSiteId": "$registrationSiteId",
  "receiveEmail": "$receiveEmail",
  "dateOfBirth": "$dob",
  "mobileNumber": "$mobileNumber",
  "gender": "$gender",
  "fuelActivationDate": "$fuelActivationDate",
  "postalCode": "$postalCode",
  "country": "$country",
  "city": "$city",
  "state": "$state",
  "bio": "$bio",
  "jpFirstNameKana": "$jpFirstNameKana",
  "jpLastNameKana": "$jpLastNameKana",
  "height": "$height",
  "weight": "$weight",
  "distanceUnit": "MILES",
  "weightUnit": "POUNDS",
  "heightUnit": "FT/INCHES"
}
EOF
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.