2010-06-23 27 views
16
function foo() { 
[email protected] 
echo $A 
} 

foo bla "hello ppl" 

Tôi muốn đầu ra là:
"bla" "hello ppl"Bash: CONCATENATE tất cả các đối số và quấn chúng với dấu ngoặc kép

gì tôi cần phải làm thay vì ellipsis?

+0

Bạn đang cố gắng làm gì?Đầu ra của 'foo' có được dùng làm đầu vào cho bất kỳ thứ gì hay bạn chỉ muốn văn bản thô? – msw

+0

Đó là nghĩa vụ phải được sử dụng làm đầu vào cho một lệnh khác (thư trong trường hợp này). – rui

+4

@rubim: sau đó tôi nghĩ rằng bạn đang làm cho nó khó khăn hơn nhiều so với nó cần. 'mail" $ @ "' sẽ cung cấp kết quả mà không có bước không phân tích cú pháp/phân tích lại. Nếu '" $ @ "' không ở trạng thái thích hợp, vui lòng cho biết bạn đang làm gì. – msw

Trả lời

3

Bạn có thể sử dụng "$ @" để điều trị mỗi tham số như, tốt, một tham số riêng biệt, và sau đó lặp qua từng thông số:

function foo() { 
for i in "[email protected]" 
do 
    echo -n \"$i\"" " 
done 
echo 
} 

foo bla "hello ppl" 
+1

+1 Giải pháp này hoạt động! Tôi lười biếng, vì vậy tôi thường thả 'trong' $ @ "'một phần và chỉ sử dụng' cho tôi ' –

+0

Tôi quên đề cập đến điều này trong câu hỏi nhưng tôi có nghĩa là để làm điều này mà không cần sử dụng một vòng lặp. Đã tìm kiếm một số mở rộng bash ma thuật hoặc một cái gì đó. – rui

3

ninjalj đã có ý tưởng đúng, nhưng việc sử dụng dấu ngoặc kép là lẻ , một phần vì những gì OP yêu cầu không thực sự là định dạng đầu ra tốt nhất cho nhiều tác vụ trình bao. Trên thực tế, tôi không thể tìm ra nhiệm vụ dự định là gì, nhưng:

function quote_args { 
    for i ; do 
     echo \""$i"\" 
    done 
} 

đặt đối số được trích dẫn trên mỗi dòng thường là cách tốt nhất để nạp các chương trình khác. Bạn không nhận được kết quả trong một hình thức bạn đã không yêu cầu:

$ quote_args this is\ a "test really" 
"this" 
"is a" 
"test really" 

nhưng nó có thể dễ dàng chuyển đổi và đây là thành ngữ rằng lời gọi shell nhất muốn:

$ echo `quote_args this is\ a "test really"` 
"this" "is a" "test really" 

nhưng trừ khi đó là đi qua một vé khác eval, các dấu ngoặc kép bổ sung có thể sẽ làm hỏng mọi thứ. Đó là, ls "is a file" sẽ liệt kê các tập tin is a file khi

$ ls `quote_args is\ a\ file` 

sẽ cố gắng liệt kê "is, a, và file" mà có thể bạn không muốn.

2

Không cần vòng lặp:

foo() { local saveIFS=$IFS; local IFS='"'; local a="${*/#/ \"}"; echo "$a"\"; IFS=$saveIFS; } 

Tiết kiệm IFS là không cần thiết trong ví dụ đơn giản này, đặc biệt là khôi phục lại nó ngay trước khi thoát chức năng, do thực tế rằng local được sử dụng. Tuy nhiên, tôi đã bao gồm nó trong trường hợp những thứ khác đang đi vào chức năng mà một thay đổi IFS có thể ảnh hưởng đến.

Ví dụ chạy:

$ foo a bcd "efg hij" k "lll mmm nnn " ooo " ppp qqq " rrr\ sss 
"a" "bcd" "efg hij" "k" "lll mmm nnn " "ooo" " ppp qqq " "rrr sss" 
6

Sử dụng tham số thay để thêm "là tiền tố và hậu tố:

function foo() { 
    A=("${@/#/\"}") 
    A=("${A[@]/%/\"}") 
    echo -e "${A[@]}" 
} 

foo bla "hello ppl" kkk 'ss ss' 

Output

"bla" "hello ppl" "kkk" "ss ss" 
21

@msw có ý tưởng đúng (lên trong nhận xét về câu hỏi).Tuy nhiên, ý tưởng khác để in tranh luận với dấu ngoặc kép: sử dụng lặp đi lặp lại tiềm ẩn của printf:

foo() { printf '"%s" ' "[email protected]"; echo ""; } 

foo bla "hello ppl" 
# => "bla" "hello ppl" 
+3

Ding! Bạn giành được giải thưởng lớn. Gấu bông khổng lồ hoặc ngân hàng đồng xu chai bia bốn chân? –

+0

Tại sao bạn thêm echo ""; cuối cùng? Không phải là không cần thiết. – EminezArtus

+0

Vì vậy, đầu ra sẽ kết thúc bằng một dòng mới. Chỉ cần để nó trông đẹp và không mess lên dấu nhắc của bạn. Tôi nhận ra nó là không cần thiết khi được gọi với một lệnh thay thế –

1

Giải pháp duy nhất vào thời điểm này mà vẫn tôn trọng những dấu xồ nguợc và dấu ngoặc kép bên trong đối số:

$ concatenate() { printf "%q"" " "[email protected]"; echo ""; } 
$ concatenate arg1 "arg2" "weird arg3\\\\\\bbut\" legal!" 
arg1 arg2 weird\ arg3\\\\\\bbut\"\ legal\! 

Thông báo các " % q "" "

% q LUAÄN được in trong một định dạng mà có thể được tái sử dụng khi cô ll đầu vào, thoát các ký tự không in được với cú pháp được đề xuất là POSIX $ ''.

ký tự đặc biệt (\, \b backspace, ...) thực sự sẽ được giải thích bởi các chương trình tiếp nhận, ngay cả khi không được hiển thị giải thích trong đầu ra thiết bị đầu cuối.

Hãy kiểm tra:

# display.sh: Basic script to display the first 3 arguments passed 
echo -e '#!/bin/bash'"\n"'echo -e "\$1=""$1"; echo -e "\$2=""$2"; echo -e "\$3=""$3"; sleep 2;' > display.sh 
sudo chmod 755 display.sh 

# Function to concatenate arguments as $ARGS 
# and "evalutate" the command display.sh $ARGS 
test_bash() { ARGS=$(concatenate "[email protected]"); bash -c "./display.sh ""$ARGS"; } 

# Test: Output is identical whatever the special characters 
./display.sh arg1 arg2 arg3 
test_bash arg1 arg2 arg3 

Nhiều thử nghiệm phức tạp:

./display.sh arg1 "arg2-1:Y\b-2:Y\\b-3:Y\\\b-4:Y\\\\b-5:Y\\\\\b-6:Y\\\\\\b" "arg3-XY\bZ-\"-1:\-2:\\-3:\\\-4:\\\\-5:\\\\\-6:\\\\\\-" 
test_bash arg1 "arg2-1:Y\b-2:Y\\b-3:Y\\\b-4:Y\\\\b-5:Y\\\\\b-6:Y\\\\\\b" "arg3-XY\bZ-\"-1:\-2:\\-3:\\\-4:\\\\-5:\\\\\-6:\\\\\\-" 

Trong display.sh, chúng tôi đang sử dụng echo -e thay vì chỉ echo hoặc printf để giải thích các ký tự đặc biệt. Đây chỉ là đại diện nếu chương trình được gọi của bạn diễn giải chúng.

-e cho phép giải thích các dấu chéo ngược thoát

Nếu -e có hiệu lực, các trình tự sau đây được công nhận:

  • \ xuyệc ngược
  • \ a alert (BEL)
  • \ b backspace
  • Vv

NB: \b là ký tự backspace, do đó nó sẽ xóa Y trong ví dụ.

Lưu ý rằng ví dụ này không phải là để được sao chép trong mã thực:

Nhờ câu trả lời được chấp nhận và Danny Hong answer trong "Cách thoát khỏi dấu ngoặc kép trong dấu ngoặc kép?"

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