bash: Jak w jednym kroku używać wielu operacji na ciągach znaków (rozwijania parametrów)?
Mam string=substr1-substr2-substr3.substr4
gdzie podciągi mają zmienną długość. Chcę wyodrębnić substr3
z string
i myślę o zrobieniu tego za pomocą rozszerzeń ${string##pattern}
i ${string%pattern}
manipulacji ciągami. Korzystając z tego podejścia, jasne jest, że muszę uruchomić ${string##*-}
i uruchomić ${string%.*}
wynikowy dodatek lub odwrotnie. Moje pytania to:
- czy to najlepszy wybór?
- Jeśli tak, jak uruchomić oba w jednym kroku? Kiedy próbuję zrobić coś podobnego
${string##*-${string%.*}}
lub${string%.*${string##*-}}
po prostu odzyskuję pełny ciąg. Zdaję sobie sprawę, że zawsze mógłbym przeprowadzić wyodrębnianie w dwóch krokach, przypisując zmienną pośrednią do wyniku pierwszego kroku, a następnie manipulując tym; ale chcę to zrobić w jednym kroku. Jak mam się do tego zabrać?
TIA!
Odpowiedzi
Dany
string=substr1-substr2-substr3.substr4
${string%.*}
jest
substr1-substr2-substr3
tak ${string##*-${string%.*}}
jest
${string##*-substr1-substr2-substr3}
co oznacza usunięcie od początku string
wszystkiego do włącznie -substr1-substr2-substr3
. Ale nie ma takiego podciągu string
, ponieważ przed nim nie ma myślnika substr1
, więc otrzymujesz oryginalny ciąg.
To, czego prawdopodobnie chcesz, to
string=substr1-substr2-substr3.substr4
result="${string%.*}" result="${result##*-}"
co prowadzi do result
zakażenia substr3
.
W Zsh można to zrobić w jednym kroku: ale to nie działa w Bash.result=${${string%.*}##*-}
W Bash jesteś ograniczony do używania rozszerzeń po prawej stronie #
lub %
, a to ci nie pomaga, ponieważ musisz usunąć części zarówno z początku, jak i końca ciągu.
Alternatywnie, jeśli $string
nie zawiera znaków nowej linii, możesz użyć
IFS=.- read -r a b c d <<< "$string"
i czytać substr3
off z c
.
W takim przypadku, w zależności od powłoki i rozmiaru łańcucha, zawartość $string
będzie przechowywana w pliku tymczasowym lub przesyłana przez potok, który read
odczyta pierwszą linię z i podzieli ją zgodnie z $IFS
.