Làm thế nào để sử dụng các biến trong dấu ngoặc đơn


11

Tôi có một ứng dụng dùng làm thuộc tính đầu vào trong dấu ngoặc kép được nhúng trong dấu ngoặc đơn. Lấy ví dụ lệnh phải này:

command -p 'cluster="cl1"'

Để tự động hóa nó, tôi đã tạo một tệp bash bằng cách sử dụng $CLUSTERnhư một biến. Làm thế nào nên là lệnh của tôi? Nói cách khác, tôi nên đặt gì thay vì cl1?

Xin lưu ý rằng, nếu tôi sửa đổi lệnh trên, nó sẽ không được chấp nhận. Ví dụ: command -p "cluster=cl1"không được chấp nhận


2
CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"
mikeerv

Một khả năng khác (nếu bạn muốn lưu trữ climà không có dấu ngoặc kép bên trong CLUSTERbiến):CLUSTER='cl1'; command -p 'cluster="'"$CLUSTER"'"'
jimmij

Cuối cùng, tôi đã tìm được câu trả lời đúng. Cảm ơn @jimmij.
Mohamad-Jaafar NEHME

Câu trả lời:


8

Có vẻ như lệnh của bạn có thể thiết lập các biến môi trường dựa trên các đối số được đưa ra trên dòng lệnh. Nó có thể là bạn có thể làm:

CLUSTER=cl1; cluster=$CLUSTER command

... Và thiết lập môi trường cho nó theo yêu cầu.

Mặt khác, trích dẫn shell thường phân định các đối số hoặc thoát các ký tự shell đặc biệt khác khỏi giải thích shell. Bạn có thể chứa (và do đó thoát) các loại trích dẫn shell khác nhau trong các loại khác dựa trên các quy tắc khác nhau:

  • "''''" - một chuỗi trích dẫn mềm có thể chứa bất kỳ số lượng trích dẫn cứng nào.
  • "\""- \dấu gạch chéo ngược có thể thoát khỏi "trích dẫn "mềm trong chuỗi trích dẫn mềm.
    • Trong bối cảnh này, \\dấu gạch chéo ngược cũng thoát khỏi chính nó, \$mã thông báo mở rộng và \newlines như được lưu ý dưới đây, nhưng được xử lý theo nghĩa đen.
  • "${expand} and then some"- một chuỗi trích dẫn mềm có thể chứa một $mở rộng shell được giải thích .
  • '"\'- một 'chuỗi trích dẫn cứng có thể chứa bất kỳ ký tự nào ngoài một 'trích dẫn cứng.
  • \- dấu gạch chéo ngược không trích dẫn sẽ thoát khỏi bất kỳ ký tự nào sau đây để giải nghĩa theo nghĩa đen - thậm chí là dấu gạch chéo ngược khác - ngoại trừ một \newline.
    • Trong \\ntrường hợp ewline, cả \dấu gạch chéo ngược và \newline đều bị xóa hoàn toàn khỏi lệnh được giải thích kết quả.
  • ${parameter+expand "$parameter"}- trích dẫn kết quả từ việc mở rộng shell hầu như không bao giờ đóng vai trò là dấu phân cách trừ một vài trường hợp đặc biệt. Tôi sẽ không mạo hiểm để mô tả những điều này hơn nữa ở đây.

Tôi coi thật kỳ quặc khi bất kỳ ứng dụng nào sẽ diễn giải các trích dẫn trong dòng lệnh của nó. Một thực tiễn như vậy không có nhiều ý nghĩa trong đó - đối với vỏ sò, ít nhất - mục đích chính của một trích dẫn thường là để phân định một lập luận. Tuy nhiên, tại lời gọi, các đối số luôn được phân định bằng các \0NULký tự và vì vậy một trích dẫn không thể phục vụ nhiều mục đích.

Ngay cả một shell thường chỉ bận tâm để giải thích các trích dẫn trong một trong các đối số gọi của nó khi nó được gọi bằng một -ccông tắc - biểu thị rằng toán hạng đầu tiên của nó thực sự là một tập lệnh shell mà nó nên chạy khi gọi. Đây là một trường hợp hai lần đánh giá đầu vào.

Tất cả những gì đã nói, bạn có thể làm một số điều để vượt qua các trích dẫn bằng chữ thông qua các đối số trên dòng lệnh. Ví dụ:

CLUSTER='"cl1"'; command -p "cluster=$CLUSTER"

Như tôi đã lưu ý trong một nhận xét trước đây, bạn có thể chứa các "trích dẫn trong một bản mở rộng được "trích dẫn.

CLUSTER=cl1; command -p "cluster=\"$CLUSTER\""

Bạn có thể thoát khỏi "với một \dấu chéo ngược trong "chuỗi trích dẫn.

CLUSTER=cl1; command -p cluster='"'"$CLUSTER"'"'

Bạn có thể xen kẽ và ghép các kiểu trích dẫn để đi đến kết quả cuối cùng mong muốn của bạn như ghi chú @jimmij ở trên .

CLUSTER=cl1; ( set -f; IFS=; command -p cluster=\"$CLUSTER\" )

Bạn có thể vô hiệu hóa cả việc tạo$IFStách tên tệp - do đó tránh phải trích dẫn $expansiontất cả - và do đó chỉ trích dẫn các trích dẫn. Đây có lẽ là quá mức cần thiết.

Cuối cùng, có một loại trích dẫn shell khác có thể được sử dụng. Như tôi đã lưu ý trước khi sh -c "$scriptlet"hình thức gọi shell thường được sử dụng để cung cấp tập lệnh của shell trên dòng lệnh. Tuy nhiên, khi $scriptlettrở nên phức tạp - chẳng hạn như khi các trích dẫn phải chứa các trích dẫn khác - việc sử dụng tài liệu ở đây và sh -sthay vào đó - trong đó trình bao được hướng dẫn cụ thể để gán tất cả các toán hạng sau cho các tham số vị trí như trong -ctrường hợp và chưa lấy kịch bản của nó từ stdin.

Nếu lệnh của bạn phải diễn giải các trích dẫn theo cách này thì tôi sẽ xem xét nó tốt hơn nếu nó có thể làm như vậy trong một đầu vào tệp. Ví dụ:

CLUSTER=cl1
command --stdin <<-SCRIPT
    cluster="$CLUSTER"
SCRIPT

Nếu bạn không trích dẫn delimiter của một <<here-documentsau đó tất cả các nội dung của nó được đối xử gần như giống hệt như họ đã "mềm trích dẫn - ngoại trừ rằng "hai dấu ngoặc kép mình không được đối xử đặc biệt. Và vì vậy, nếu chúng ta chạy ở trên với catthay thế:

CLUSTER=cl1
cat <<-SCRIPT
        cluster="$CLUSTER"
SCRIPT

... nó in ...

cluster="cl1"

1

Giống như mikeerv đã viết:

 CLUSTER='"cl1"'; command -p "cluster=$CLUSTER" 

"Double quote" mỗi đen có chứa dấu cách / metacharacters và mỗi mở rộng: "$var", "$(command "$var")", "${array[@]}", "a & b". Sử dụng 'single quotes'mã hoặc đen $'s: 'Costs $5 US', ssh host 'echo "$HOSTNAME"'. Xem
http://mywiki.wooledge.org/Quotes
http://mywiki.wooledge.org/Argument
http://wiki.bash-hackers.org/syntax/words


Bạn nói đúng, cảm ơn bạn. Nhưng, còn tự động hóa thì sao? Giả sử tôi muốn đọc CLUSTER? Tôi sẽ bị mắc kẹt một lần nữa với cùng một vấn đề: biến trong các trích dẫn đơn
Mohamad-Jaafar NEHME

@Moi - tự động hóa không phải là vấn đề lớn, mặc dù bạn sẽ phải vệ sinh biến số của các "ký tự - chỉ đầu tiên và cuối cùng là đủ. Vấn đề thực sự ở đây là ứng dụng của bạn diễn giải các trích dẫn trong một cuộc tranh luận. Giải thích một trích dẫn trong một cuộc tranh luận gần như không bao giờ là một ý tưởng hay bởi vì một trích dẫn chỉ nên là một phương tiện để phân định một đối số - và trong lời mời rằng việc phân định được xử lý bởi \0NULs trong mọi trường hợp. Có lẽ có một cách tốt hơn để truyền thông tin bạn muốn vào ứng dụng? Giống như một command --'script=/path/to/some/file'cái gì đó?
mikeerv
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.