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?

Aug 15 2020

Tôi có string=substr1-substr2-substr3.substr4nơi các chuỗi con có độ dài thay đổi. Tôi muốn trích xuất substr3từ stringvà đ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}${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à:

  1. Đây có phải là sự lựa chọn tốt nhất?
  2. 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

2 ilkkachu Aug 15 2020 at 20:39

Được

string=substr1-substr2-substr3.substr4

${string%.*}

substr1-substr2-substr3

vì vậy, ${string##*-${string%.*}}

${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 resultcó 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 $stringkhô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 substr3từ 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 $stringsẽ đượ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 readsẽ đọc dòng đầu tiên từ đó và chia nó theo $IFS.