Đây là cách tôi khuyên bạn nên làm điều đó, và tôi sẽ giải thích tại sao, nhưng trước tiên tôi muốn nói về điều gì khác ...
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
Rất nhiều giải pháp chuyên sâu khác ở đây dường như cho thấy rằng bằng cách nào đó bạn có thể ảnh hưởng đến nội dung của biến shell bằng cách thay đổi phương pháp mở rộng nó. Tôi có thể đảm bảo với bạn đây không phải là trường hợp.
string="some stuff here \
some more stuff here."
echo $string ${#string}
echo "$string" "${#string}"
ĐẦU RA
some stuff here some more stuff here. 53
some stuff here some more stuff here. 53
Những gì bạn thấy ở trên trước tiên là mở rộng phân chia trường, sau đó là báo cáo về số byte cho biến nguồn của mở rộng, sau đó là mở rộng được phân tách bằng trích dẫn và cùng một số đếm byte. Mặc dù đầu ra có thể khác nhau, nội dung của biến shell $stringkhông bao giờ thay đổi ngoại trừ khi gán.
Hơn nữa, nếu bạn không hiểu tại sao lại như vậy, bạn nhất định sẽ gặp phải một số bất ngờ rất khó chịu sớm hơn sau này. Hãy thử lại lần nữa, nhưng trong những điều kiện hơi khác nhau.
IFS=sf
echo $string ${#string}
echo "$string" "${#string}"
Giống $stringnhau - môi trường khác nhau.
ĐẦU RA
ome tu here ome more tu here. 53
some stuff here some more stuff here. 53
Phân tách trường xảy ra dựa trên các dấu phân cách trường được xác định trong $IFS. Có hai loại dấu phân cách - $IFSkhoảng trắng và $IFSbất cứ thứ gì khác. Theo mặc định $IFSđược gán dòng mới của tab không gian giá trị - là ba $IFSgiá trị khoảng trắng có thể có . Tuy nhiên, nó có thể dễ dàng thay đổi, như bạn có thể thấy ở trên, và có thể có tác động mạnh mẽ đến việc mở rộng phân chia trường.
$IFSkhoảng trắng sẽ tách biệt theo trình tự đến một trường duy nhất - và đây là lý do tại sao echoviệc mở rộng chứa bất kỳ chuỗi không gian nào khi $IFSchứa một khoảng trắng sẽ chỉ đánh giá một không gian duy nhất - bởi vì echonối các đối số của nó trên các khoảng trắng. Nhưng bất kỳ giá trị không phải khoảng trắng nào cũng sẽ không tồn tại theo cùng một cách và mỗi dấu phân cách xuất hiện luôn có một trường cho chính nó - như có thể thấy trong phần mở rộng công cụ ở trên.
Đây không phải là tồi tệ nhất của nó. Hãy xem xét cái này khác $string.
IFS=$space$tab$newline
cd emptydir
string=" * * * \
* * * "
echo $string ${#string}
echo "$string" "${#string}"
ĐẦU RA
* * * * * * 30
* * * * * * 30
Có vẻ ổn, phải không? Vâng, hãy thay đổi môi trường một lần nữa.
touch file1 file2 file3 file4 file5
echo $string ${#string}
echo "$string" "${#string}"
ĐẦU RA
file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 file1 file2 file3 file4 file5 30
* * * * * * 30
Ái chà.
Theo mặc định, shell sẽ mở rộng các tên tập tin nếu nó có thể khớp với chúng. Điều này xảy ra sau khi mở rộng tham số và tách trường theo thứ tự phân tích cú pháp và do đó, bất kỳ chuỗi không trích dẫn nào cũng dễ bị tổn thương theo cách này. Bạn có thể tắt hành vi này set -fnếu bạn muốn, nhưng mọi vỏ tương thích POSIX sẽ luôn luôn toàn cầu theo mặc định.
Đây là loại nội dung bạn gặp phải khi bạn bỏ dấu ngoặc kép trên bản mở rộng cho phù hợp với sở thích thụt lề của bạn. Và ngay cả như vậy, trong mọi trường hợp, bất kể hành vi mở rộng của nó, giá trị thực tế $stringvẫn luôn là bất cứ khi nào bạn được chỉ định lần cuối. Vì vậy, hãy trở lại điều đầu tiên.
set -- 'Arg 1: Line 1.' \
'Arg 2: Line 2.' \
'and so on for' \
'as long as you might like.'
var="$*"
echo "$var" "${#var}"
ĐẦU RA
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like. 70
Tôi tin rằng đây là một cách xa hơn để điều chỉnh cú pháp shell theo sở thích thụt lề của bạn. Những gì tôi đang làm ở trên là gán từng chuỗi riêng lẻ cho một tham số vị trí - mỗi chuỗi có thể được tham chiếu theo số như $1hoặc ${33}- và sau đó gán các giá trị được nối của chúng để $varsử dụng tham số shell đặc biệt $*.
Cách tiếp cận này không miễn dịch $IFS, thậm chí là như vậy. Tuy nhiên, tôi xem xét mối quan hệ của nó với $IFSmột lợi ích gia tăng về mặt này. Xem xét:
IFS=\ ;space_split="$*"
IFS=/; slash_split="$*";IFS='
';new_line_split="$*"
echo "$space_split"
echo "$slash_split"
echo "$new_line_split"
ĐẦU RA
Arg 1: Line 1. Arg 2: Line 2. and so on for as long as you might like.
Arg 1: Line 1./Arg 2: Line 2./and so on for/as long as you might like.
Arg 1: Line 1.
Arg 2: Line 2.
and so on for
as long as you might like.
Như bạn có thể thấy, $*nối từng "$@"đối số trên byte đầu tiên trong $IFS. Vì vậy, việc lưu giá trị của nó trong khi $IFSđược gán khác nhau sẽ có các dấu phân cách trường khác nhau cho mỗi giá trị được lưu. Nhân tiện, những gì bạn thấy ở trên là giá trị bằng chữ cho mỗi biến. Nếu bạn không muốn có dấu phân cách nào cả, bạn sẽ làm:
IFS=;delimitless="$*"
echo "$delimitless" "${#delimitless}"
ĐẦU RA
Arg 1: Line 1.Arg 2: Line 2.and so on foras long as you might like. 67