Nối các đối số bash thành một chuỗi có khoảng trắng


39

Tôi đang cố gắng nối tất cả các đối số vào một hàm Bash thành một chuỗi duy nhất với các khoảng trắng ngăn cách mỗi đối số. Tôi cũng cần phải có chuỗi bao gồm các trích dẫn duy nhất xung quanh toàn bộ chuỗi.

Đây là những gì tôi có cho đến nay ...

$array=("$@")
str="\'"
for arg in "${array[@]}"; do
    let $str=$str+$arg+" "
done
let $str=$str+"\'"

Rõ ràng điều này không hiệu quả nhưng tôi tự hỏi liệu có cách nào để đạt được điều này không?

Câu trả lời:


54

Tôi tin rằng điều này làm những gì bạn muốn. Nó sẽ đặt tất cả các đối số trong một chuỗi, được phân tách bằng dấu cách, với các dấu ngoặc đơn xung quanh tất cả:

str="'$*'"

$*tạo ra tất cả các đối số tập lệnh được phân tách bằng ký tự đầu tiên $IFS, theo mặc định, là một khoảng trắng.

Trong một chuỗi trích dẫn kép, không cần phải thoát dấu ngoặc đơn.

Thí dụ

Hãy để chúng tôi đặt ở trên trong một tập tin kịch bản:

$ cat script.sh 
#!/bin/sh
str="'$*'"
echo "$str"

Bây giờ, hãy chạy tập lệnh với các đối số mẫu:

$ sh script.sh one two three four 5
'one two three four 5'

Kịch bản này là POSIX. Nó sẽ làm việc với bashnhưng nó không yêu cầu bash.

Một biến thể: nối với dấu gạch chéo thay vì dấu cách

Chúng ta có thể thay đổi từ không gian sang nhân vật khác bằng cách điều chỉnh IFS:

$ cat script.sh 
#!/bin/sh
old="$IFS"
IFS='/'
str="'$*'"
echo "$str"
IFS=$old

Ví dụ:

$ sh script.sh one two three four       
'one/two/three/four'

Được rồi, điều này làm việc tuyệt vời và làm chính xác những gì tôi cần. Tôi đang cố gắng sử dụng điều này để thay đổi thư mục thành một thư mục có khoảng trắng trong tên chỉ bằng cách sử dụng các đối số. Điều cuối cùng tôi cần điều này là tạo ra một hàm sẽ thay đổi các thư mục mà không cần phải gõ các dấu nháy đơn nếu thư mục có các từ được đặt cách nhau. Những gì tôi vừa thử là như sau: cdm () {str = "'$ *'" cd $ str} Nó chỉ truy cập đối số đầu tiên trong str Ví dụ: cdm test 2 Kết quả: 'test: Không có tệp hoặc thư mục như vậy
Schwagmister

@Schwagmister: Bạn có thể lưu nó vào một biến (chuỗi) nếu bạn muốn, nhưng, nếu bạn không đặc biệt cần phải làm điều đó, tôi nghĩ cd "$*"sẽ đủ tốt.
Scott

@Schwagmister Các trích dẫn duy nhất không hữu ích ở đó. Hãy thử: cdm(){ str="$*"; cd "$str"; }hoặc, như Scott gợi ý , cdm(){ cd "$*"; }. Ngoài ra, hãy lưu ý rằng $*thay thế nhiều không gian liên tiếp bằng một không gian duy nhất. Nếu tên thư mục của bạn có thể có nhiều khoảng trắng hoặc tab hoặc dòng mới liên tiếp, thì những ký tự đó thực sự cần phải được thoát trước khi chúng được chuyển đến cdmhàm.
John1024

Vì vậy, nếu nó là một cái gì đó giống như thử nghiệm 2 thử nghiệm 1, làm thế nào để làm cho lệnh cd này hoạt động chính xác? Ngoài ra đây là sự giúp đỡ tuyệt vời tôi thực sự đánh giá cao nó các bạn. @Scott
Schwagmister

@Schwagmister Cách tốt nhất là đặt dấu ngoặc đơn trên dòng lệnh khi gọi cdmnhư trong : cdm 'test 2 trial 1'. Điều này sẽ xử lý tất cả các trang viên của tên lạ. Tuy nhiên, miễn là các khoảng trắng được giới hạn trong các không gian đơn, thì cdmsau đó nó có thể được chạy dưới dạng cdm test 2 trial 1.
John1024

5

Nó dễ hơn bạn nghĩ:

#!/bin/bash
array="${@}"

echo $array

chmod + x đó và chạy nó:

$ ./example.sh --foo bar -b az 
--foo bar -b az
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.