2009-12-30 1 views
107

Tôi đang viết tập lệnh bash nơi tôi cần chuyển chuỗi chứa dấu cách vào hàm trong tập lệnh bash của tôi.Chuyển chuỗi có dấu cách làm đối số hàm trong bash

Ví dụ:

#!/bin/bash 

myFunction 
{ 
    echo $1 
    echo $2 
    echo $3 
} 

myFunction "firstString" "second string with spaces" "thirdString" 

Khi chạy, đầu ra tôi mong đợi là:

firstString 
second string with spaces 
thirdString 

Tuy nhiên, những gì thực sự là đầu ra là:

firstString 
second 
string 

Có cách nào để vượt qua một chuỗi với không gian như là một đối số duy nhất cho một chức năng trong bash?

+0

trình cho tôi ... Tôi sử dụng cú pháp đầy đủ cho các chức năng mặc dù" chức năng bla () {echo $ 1; } ", không thể viết ngắn gọn thành một lớp lót. Không chắc chắn nó tạo nên sự khác biệt. Phiên bản bash nào? – Eugene

+3

thử' echo "$ @" 'hoặc' cho i trong "$ @"; echo echo $ i; Việc này được đề cập rất rõ ràng trong tất cả các tài liệu 'bash' trong phần' tham số vị trí'. – Samveen

+1

Tôi đã gặp vấn đề tương tự, cố chuyển một chuỗi được trích dẫn thành tham số và chỉ là chuỗi đầu tiên từ của chuỗi được công nhận là một phần của tham số. Đề xuất của Samveen thay đổi $ 1 thành $ @ làm việc cho tôi. Lưu ý rằng tôi chỉ chuyển một tham số cho hàm, nhưng nếu tôi chuyển nhiều hơn bằng câu lệnh for sẽ có –

Trả lời

116

bạn nên đặt dấu ngoặc kép và cũng có thể, khai báo hàm của bạn sai.

myFunction() 
{ 
    echo "$1" 
    echo "$2" 
    echo "$3" 
} 

Và cũng giống như các tính năng khác, nó cũng phù hợp với tôi. Cho chúng tôi biết bạn đang sử dụng phiên bản shell nào.

+1

Điều này cũng rất tốt cho tôi. chúng tôi đang gọi một hàm khác bên trong myFu nction sau đó chuyển đối số bằng dấu ngoặc kép. Chúc mừng :) – minhas23

+1

Bạn có thể giải thích lý do tại sao người ta cần báo giá? Tôi đã thử cả hai có và không có, và nó đã không làm việc cho tôi. Tôi đang sử dụng Ubuntu 14.04, GNU bash, phiên bản 4.3.11 (1) -release (x86_64-pc-linux-gnu). * Làm gì * cho tôi đang sử dụng $ @ (có hoặc không có dấu ngoặc kép). –

4

Định nghĩa của bạn về myFunction là sai. Nó nên là:

myFunction() 
{ 
    # same as before 
} 

hay:

function myFunction 
{ 
    # same as before 
} 

Dù sao, nó có vẻ tốt đẹp và hoạt động tốt đối với tôi trên Bash 3.2.48.

-2

Đã có cùng một loại vấn đề và trên thực tế vấn đề không phải là chức năng cũng không gọi hàm, nhưng những gì tôi đã chuyển làm đối số cho hàm.

Hàm được gọi từ phần thân của tập lệnh - 'chính' - vì vậy tôi đã chuyển "st1 ab" "st2 cd" "st3 ef" từ dòng lệnh và chuyển nó đến hàm bằng hàm myFunction $ *

$ * gây ra sự cố khi nó mở rộng thành một tập hợp các ký tự sẽ được diễn giải trong lời gọi hàm bằng cách sử dụng khoảng trắng làm dấu phân cách.

Giải pháp là thay đổi cuộc gọi đến hàm trong xử lý đối số rõ ràng từ 'chính' đối với hàm: cuộc gọi sau đó sẽ là myFunction "$ 1" "$ 2" "$ 3" để giữ khoảng trắng bên trong chuỗi các dấu ngoặc kép sẽ phân định các đối số ... Vì vậy, nếu một tham số có thể chứa dấu cách, nó sẽ được xử lý một cách rõ ràng trong tất cả các cuộc gọi của các hàm.

Vì đây có thể là lý do cho các tìm kiếm dài để vấn đề này, nó có thể là khôn ngoan không bao giờ sử dụng $ * để vượt qua đối số ...

Hope this helps một ai đó, một ngày nào đó, ở đâu đó ... tháng một

+0

Câu trả lời đúng là '" $ @ "', không phải tất cả trích dẫn '" $ 1 "', '" $ 2 "', ... các tham số vị trí cũng không phải '$ *'. – Samveen

0

bạn có thể có một phần mở rộng của vấn đề này trong trường hợp văn bản ban đầu của bạn đã được thiết lập vào một biến kiểu chuỗi, ví dụ:

function status(){  
    if [ $1 != "stopped" ]; then 
    artist="ABC"; 
    track="CDE"; 
    album="DEF"; 
    status_message="The current track is $track at $album by $artist"; 
    echo $status_message; 
    read_status $1 "$status_message"; 
    fi 
} 

function read_status(){ 
    if [ $1 != "playing" ]; then 
    echo $2 
    fi 
} 

trong trường hợp này nếu bạn không vượt qua biến STATUS_MESSAGE về phía trước như chuỗi (được bao quanh bởi "") nó sẽ là chia thành một loạt các đối số khác nhau.

"$ biến": Các ca khúc hiện nay là Bộ Giáo Dục California DEF bởi ABC

$ biến: Các

+0

OP sử dụng 'myFunction" firstString "" chuỗi thứ hai có dấu cách "" thirdString "' và nó không hoạt động cho anh ta.Vì vậy, những gì bạn đề xuất không áp dụng cho câu hỏi này. – doubleDown

14

Một giải pháp cho vấn đề trên là để thiết lập mỗi chuỗi cho một biến, cuộc gọi hàm có các biến được ký hiệu bằng ký hiệu đô la theo số \$. Sau đó, trong hàm sử dụng eval để đọc biến và đầu ra như mong đợi.

#!/usr/bin/ksh 

myFunction() 
{ 
    eval string1="$1" 
    eval string2="$2" 
    eval string3="$3" 

    echo "string1 = ${string1}" 
    echo "string2 = ${string2}" 
    echo "string3 = ${string3}" 
} 

var1="firstString" 
var2="second string with spaces" 
var3="thirdString" 

myFunction "\${var1}" "\${var2}" "\${var3}" 

exit 0 

Output là sau đó:

string1 = firstString 
    string2 = second string with spaces 
    string3 = thirdString 

Trong cố gắng để giải quyết một vấn đề tương tự như sau, tôi đã chạy vào vấn đề của UNIX suy nghĩ của tôi đã biến không gian delimeted. Tôi đã cố gắng để vượt qua một chuỗi phân cách đường ống đến một chức năng sử dụng awk để thiết lập một loạt các biến sau đó được sử dụng để tạo ra một báo cáo. Ban đầu tôi đã thử các giải pháp được đăng bởi ghostdog74 nhưng không thể làm cho nó hoạt động vì không phải tất cả các tham số của tôi đều được thông qua trong dấu ngoặc kép. Sau khi thêm dấu ngoặc kép vào mỗi tham số, nó bắt đầu hoạt động như mong đợi.

Dưới đây là trạng thái trước của mã của tôi và hoạt động hoàn toàn sau trạng thái.

Trước - Non Mã chức năng

#!/usr/bin/ksh 

#******************************************************************************* 
# Setup Function To Extract Each Field For The Error Report 
#******************************************************************************* 
getField(){ 
    detailedString="$1" 
    fieldNumber=$2 

    # Retrieves Column ${fieldNumber} From The Pipe Delimited ${detailedString} 
    # And Strips Leading And Trailing Spaces 
    echo ${detailedString} | awk -F '|' -v VAR=${fieldNumber} '{ print $VAR }' | sed 's/^[ \t]*//;s/[ \t]*$//' 
} 

while read LINE 
do 
    var1="$LINE" 

    # Below Does Not Work Since There Are Not Quotes Around The 3 
    iputId=$(getField "${var1}" 3) 
done<${someFile} 

exit 0 

Sau - chức năng Mã

#!/usr/bin/ksh 

#******************************************************************************* 
# Setup Function To Extract Each Field For The Report 
#******************************************************************************* 
getField(){ 
    detailedString="$1" 
    fieldNumber=$2 

    # Retrieves Column ${fieldNumber} From The Pipe Delimited ${detailedString} 
    # And Strips Leading And Trailing Spaces 
    echo ${detailedString} | awk -F '|' -v VAR=${fieldNumber} '{ print $VAR }' | sed 's/^[ \t]*//;s/[ \t]*$//' 
} 

while read LINE 
do 
    var1="$LINE" 

    # Below Now Works As There Are Quotes Around The 3 
    iputId=$(getField "${var1}" "3") 
done<${someFile} 

exit 0 
0

giải pháp đơn giản mà làm việc cho tôi - trích dẫn $ @

Test(){ 
    set -x 
    grep "[email protected]" /etc/hosts 
    set +x 
} 
Test -i "3 rb" 
+ grep -i '3 rb' /etc/hosts 

tôi có thể xác minh thực tế lệnh grep (nhờ thiết lập -x).

0

Giải pháp đơn giản nhất cho vấn đề này là bạn chỉ cần sử dụng \ "cho không gian tách đối số khi chạy một kịch bản shell #!/bin/bash myFunction { echo $1 echo $2 echo $3 } myFunction "firstString" "\"Hello World\"" "thirdString"