bash: Jak w jednym kroku używać wielu operacji na ciągach znaków (rozwijania parametrów)?
Mam string=substr1-substr2-substr3.substr4gdzie podciągi mają zmienną długość. Chcę wyodrębnić substr3z stringi 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 stringwszystkiego 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 resultzakaż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 $stringnie zawiera znaków nowej linii, możesz użyć
IFS=.- read -r a b c d <<< "$string"
i czytać substr3off z c.
W takim przypadku, w zależności od powłoki i rozmiaru łańcucha, zawartość $stringbędzie przechowywana w pliku tymczasowym lub przesyłana przez potok, który readodczyta pierwszą linię z i podzieli ją zgodnie z $IFS.