2012-02-28 24 views
10

Tôi đang cố gắng thay thế một biến chuỗi, chứa nhiều từ được trích dẫn, làm tham số cho một lệnh.Làm cách nào để thay thế các chuỗi nhiều từ, được trích dẫn thành các đối số?

Do đó, đưa ra ví dụ kịch bản sau đây (Lưu ý -x trong công việc, khiến đầu ra phải đăng nhập để stderr),

#!/bin/bash -x 

myArg="\"hello\" \"world\"" 
echo "string is:" $myArg 

exit 

nào cho chúng ta,

+ myArg='"hello" "world"' 
+ echo 'string is:' '"hello"' '"world"' 
string is: "hello" "world" 
+ exit 


Dòng hai hiển thị những gì thực sự được truyền cho lệnh; bash đã thêm dấu nháy đơn cho mỗi từ trong chuỗi. Nếu tôi thay vào đó, do đó, báo giá "$ myArg", điều tương tự cũng xảy ra nhưng đối với toàn bộ chuỗi thay vì mỗi từ.

Bây giờ, hãy tưởng tượng rằng thay vì echo, chúng tôi đang chuyển chuỗi tới chương trình trong đó một số đối số cần phải được trích dẫn mẫu, chẳng hạn như "*" (không được mở rộng bởi vỏ).

Để làm rõ, tôi không muốn thêm một dấu ngoặc đơn nào trong suốt quá trình mở rộng. Làm thế nào tôi có thể đạt được điều này?

+0

Bạn đang làm gì?Trừ khi bạn đang làm một cái gì đó icky với 'eval' cho dù chuỗi thông qua chương trình có chứa' "*" 'hoặc' * 'không quan trọng nhiều. – Sorpigal

+0

Đối với bất kỳ ai đang nhầm lẫn: Lưu ý '-x' trong shebang, làm cho đầu ra được ghi lại. – user123444555621

+0

@ Pumbaa80, quả thật vậy, tôi đã thêm vào đó làm rõ câu hỏi. –

Trả lời

13

không sử dụng dấu ngoặc kép, sử dụng một mảng (xem BashFAQ #050):

$ myArgs=("hello" "world" "multiword arg with * ?") 
+ myArgs=("hello" "world" "multiword arg with * ?") 
$ echo "${myArgs[@]}" 
+ echo hello world 'multiword arg with * ?' 
hello world multiword arg with * ? 

Nếu nó thực sự cần phải ở dạng chuỗi được trích dẫn trong một chuỗi, bạn sẽ phải sử dụng một cái gì đó như eval "echo $myArg" (có thể gây ra một số lỗi thực sự khó chịu, nếu bạn không cẩn thận) hoặc phân tích cú pháp đó (sẽ rất khó khăn).

+0

Cách tiếp cận mảng này hoạt động hoàn hảo, cảm ơn rất nhiều! ps. Bất kỳ op in nào từ một vỏ bọc con được trình bày bởi shell cha, vì vậy bất kỳ câu lệnh 'eval' nào như vậy đều cho cùng một kết quả xấu. –

4

Nếu bạn muốn vượt qua một giá trị biến như một tham số (99% các trường hợp trên SO), chỉ cần sử dụng đúng quoting:

arg="foo bar" 
command "$arg" 

Nếu bạn muốn vượt qua nhiều đối số, sử dụng các mảng:

args=("foo bar" "baz ban" bay) 
command "${args[@]}" 
+0

Được làm rõ bởi @ gordon-davisson, Mảng đã thực sự là câu trả lời, cảm ơn rất nhiều! –

0

Tôi không nghĩ rằng nó đang làm những gì bạn nghĩ rằng nó đang làm.

[~]$ myArg="\"hello\" \"world\"" 
[~]$ echo "string is:" $myArg 
string is: "hello" "world" 

Tôi không thấy thêm dấu ngoặc kép nào trong số bất kỳ loại nào echo nhận được ba chuỗi đối số.

[~]$ cargs(){ echo $#; } 
[~]$ cargs "string is:" $myArg 
3 

Bash sẽ mở rộng biến đầu tiên, vì vậy

cargs "string is:" $myArg 

trở thành (mặc dù không có sự đen backslashes- đây là lý do tại sao chuỗi thoát là một Pita)

cargs "string is:" "\"hello\"" "\"world\"" 

Và mảng args là:

0x00:string is:0 
0x0B:"hello"0 
0x13:"world"0 
0x1B:0 

Bây giờ, nếu bạn thêm *, hoặc mở rộng đường dẫn glob trong một trong số đó, Bash sẽ vào thời điểm này mở rộng nó, trừ khi bạn thoát khỏi nó, hoặc sử dụng dấu nháy đơn trong lệnh chữ của bạn.

[~]$ cargs "string is:" $myArg * 
19 
[~]$ cargs "string is:" $myArg "\*" 
4 
[~]$ cargs "string is:" $myArg '*' 
4 
+0

Echo's * output * in ra các từ được trích dẫn một cách hoàn hảo, nhưng các đối số đầu vào được truyền tới echo (như được hiển thị trên dòng hai của đầu ra gỡ lỗi trong câu hỏi) là trích dẫn đơn đôi ('' str ''). là đầu vào vô nghĩa cho công cụ tôi đang sử dụng. –

Các vấn đề liên quan