bash: Làm thế nào để sử dụng nhiều thao tác chuỗi (mở rộng tham số) trong một bước?
Tôi có string=substr1-substr2-substr3.substr4
nơi các chuỗi con có độ dài thay đổi. Tôi muốn trích xuất substr3
từ string
và đang nghĩ đến việc làm điều đó bằng cách sử dụng mở rộng thao tác chuỗi ${string##pattern}
và ${string%pattern}
. Sử dụng cách tiếp cận này, rõ ràng là tôi cần chạy ${string##*-}
và chạy ${string%.*}
trên bản mở rộng kết quả hoặc ngược lại. Câu hỏi của tôi là:
- Đây có phải là sự lựa chọn tốt nhất?
- Nếu có, làm cách nào để chạy cả hai trong một bước? Khi tôi cố gắng làm điều gì đó như
${string##*-${string%.*}}
hoặc${string%.*${string##*-}}
tôi chỉ nhận lại chuỗi đầy đủ. Tôi nhận ra rằng tôi luôn có thể thực hiện trích xuất theo hai bước bằng cách gán một biến trung gian cho kết quả của bước đầu tiên, và sau đó thao tác điều đó; nhưng tôi muốn làm điều đó trong một bước. Làm thế nào để tôi đi về nó?
TIA!
Trả lời
Được
string=substr1-substr2-substr3.substr4
${string%.*}
Là
substr1-substr2-substr3
vì vậy, ${string##*-${string%.*}}
là
${string##*-substr1-substr2-substr3}
có nghĩa là xóa ngay từ đầu string
, mọi thứ cho đến và bao gồm -substr1-substr2-substr3
. Nhưng không có chuỗi con nào như vậy string
, vì không có dấu gạch ngang phía trước substr1
, vì vậy bạn sẽ có được chuỗi ban đầu.
Điều bạn có thể muốn là
string=substr1-substr2-substr3.substr4
result="${string%.*}" result="${result##*-}"
mà dẫn đến result
có chứa có substr3
.
Trong Zsh, bạn có thể làm điều đó trong một bước: nhưng điều đó không hiệu quả trong Bash.result=${${string%.*}##*-}
Trong Bash, bạn bị hạn chế sử dụng các phần mở rộng ở phía bên phải của #
hoặc %
và điều đó không giúp bạn ở đây vì bạn cần phải xóa các phần khỏi cả phần đầu và phần cuối của chuỗi.
Ngoài ra, nếu $string
không chứa các ký tự dòng mới, bạn có thể sử dụng
IFS=.- read -r a b c d <<< "$string"
và đọc substr3
từ c
.
Trong trường hợp đó, tùy thuộc vào trình bao và kích thước của chuỗi, nội dung của $string
sẽ được lưu trữ trong một tệp tạm thời hoặc được cung cấp thông qua một đường ống read
sẽ đọc dòng đầu tiên từ đó và chia nó theo $IFS
.