Thay thế biến Bash trong chuỗi JSON


9

Tôi đang cố gắng tạo JSON trong BASH trong đó một trong các trường dựa trên kết quả của lệnh trước đó

BIN=$(cat next_entry)
OUTDIR="/tmp/cpupower/${BIN}"
echo $OUTDIR
JSON="'"'{"hostname": "localhost", "outdir": "${OUTDIR}", "port": 20400, "size": 100000}'"'"
echo $JSON

Kịch bản trên khi được thực thi, trả về:

/tmp/cpupower/0
, port: 20400, size: 100000}': /tmp/cpupower/0

Làm thế nào tôi có thể thay thế chính xác các biến bên trong các chuỗi đa trích dẫn này?


1
Tôi nghĩ rằng tôi vừa nhìn thấy một con sâu bướm hút thuốc hookah và một con mèo cười toe toét. (1) Tôi không thấy bất kỳ cách nào mà các lệnh được trình bày trong câu hỏi có thể tạo ra đầu ra được trình bày trong câu hỏi. (Lưu ý rằng OUTDIRbiến dường như được mở rộng vào giá trị của JSON, và dấu ngoặc kép quanh "port""size"là hiểu sao vắng mặt.) (2) Có vẻ như rõ ràng với tôi rằng các BINbiến là nhận được một vận chuyển trở lại trong nó (từ next_entrytập tin); và vấn đề rõ ràng đã biến mất mà không giải quyết được vấn đề đó.
G-Man nói 'Phục hồi Monica'

Câu trả lời:


14
JSON=\''{"hostname": "localhost", "outdir": "'"$OUTDIR"'", "port": 20400, "size": 100000}'\'

Đó là nhận ra các trích dẫn duy nhất cho việc mở rộng $OUTDIR. Chúng tôi đã đặt sự mở rộng đó bên trong dấu ngoặc kép cho biện pháp tốt mặc dù đối với phép gán biến vô hướng không thực sự cần thiết.

Khi bạn chuyển $JSONbiến sang echo, các trích dẫn cần thiết mặc dù để vô hiệu hóa toán tử split + global. Tốt nhất nên tránh echodữ liệu tùy ý:

printf '%s\n' "$JSON"

Mát mẻ. Những công việc này! Có lẽ bạn có thể giải thích thêm một chút về lý do tại sao điều này hoạt động? Ý nghĩa của đầu tiên là gì \'. Tôi không tin rằng tôi đã thấy điều đó trên một số ví dụ tôi đã thấy trên SO / unix.stackexchange.
sư Prasad

Dấu gạch chéo ngược trước 'bảo shell xử lý' như bất kỳ ký tự bình thường nào, thay vì diễn giải nó như một dấu phân cách chuỗi. Dấu gạch chéo ngược có thể được sử dụng trước một vài ký tự khác. Ví dụ: \\ sẽ đại diện cho chính \ ký tự và \ "có nghĩa là" văn học nhân vật. Xem ví dụ \ n trong đối số printf ở trên, trong đó printf diễn giải \ n là ký tự nguồn cấp dữ liệu.
Tăng cường

1
(1) Tôi tin rằng bạn cần phải có được rõ ràng hơn rằng sự thay đổi từ "'"đến \'là một hoàn toàn phong cách (ví dụ, tùy ý) một, và rằng sự thay đổi nội dung duy nhất bạn làm là dấu ngoặc kép quanh $OUTDIR. (Bạn cũng có thể đã đề cập rằng việc niềng răng ${OUTDIR}chỉ đơn giản là không cần thiết.) (2) Vui lòng xem nhận xét của tôi về câu hỏi và cho tôi biết liệu tôi có bị ảo giác không (nghĩa là tôi đã bỏ qua điều gì đó, hay bạn?).
G-Man nói 'Phục hồi Monica'

@ G-Man, tôi đồng ý với bạn.
Stéphane Chazelas

3

Câu trả lời của Stéphane là tuyệt vời, và được đánh giá cao. Đây chỉ là một mẹo; thay vì làm

BIN=$(cat next_entry)

Bạn có thể làm:

BIN=$(<next_entry)

Và do đó tiết kiệm sinh sản thêm một quá trình. Đọc thêm ở đây .


2
Nó chỉ lưu sinh ra một quá trình bổ sung trong ksh (nơi cú pháp đó xuất phát) và zsh, không phải bash. Trong bash, nó chỉ lưu thực thi cat, bashvẫn sinh ra một quy trình bổ sung. Xem Hiểu Hiểu thay thế lệnh đọc tệp của Bash để biết thêm chi tiết.
Stéphane Chazelas

0

Nếu bạn đã kết thúc ở đây cố gắng sử dụng các lệnh AWS, câu trả lời của @ Stéphane Chazelas gần như hoạt động. Ở đây, các trích dẫn thoát ban đầu (\ ') là không cần thiết, chúng thực sự phá vỡ lệnh.

IP=$(curl ipecho.net/plain ; echo)

aws ec2 authorize-security-group-ingress --group-id sg-**************** \
    --ip-permissions '[{"IpProtocol": "tcp", "FromPort": 15000, "ToPort": 15000, "IpRanges": [{"CidrIp": "'"$IP/32"'", "Description": "Service A"}]}]'

^ Điều này hoạt động tốt

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.