bash: Как использовать несколько строковых манипуляций (расширение параметров) за один шаг?
У меня string=substr1-substr2-substr3.substr4где подстроки переменной длины. Я хочу извлечь substr3из него stringи подумываю сделать это с помощью расширений ${string##pattern}и ${string%pattern}строковых манипуляций. Используя этот подход, ясно, что мне нужно запустить ${string##*-}и запустить ${string%.*}получившееся расширение или наоборот. Мои вопросы:
- это лучший выбор?
- Если да, как мне запустить оба за один шаг? Когда я пытаюсь сделать что-то вроде
${string##*-${string%.*}}или${string%.*${string##*-}}просто получаю полную строку. Я понимаю, что всегда могу выполнить извлечение в два этапа, назначив промежуточную переменную результату первого шага, а затем манипулируя этим; но я хочу сделать это за один шаг. Как мне это сделать?
TIA!
Ответы
Дано
string=substr1-substr2-substr3.substr4
${string%.*} является
substr1-substr2-substr3
Итак, ${string##*-${string%.*}}это
${string##*-substr1-substr2-substr3}
что означает удалить с самого начала stringвсе до и включительно -substr1-substr2-substr3. Но такой подстроки нет string, так как перед ней нет тире substr1, поэтому вы получаете исходную строку.
Вы, вероятно, хотите
string=substr1-substr2-substr3.substr4
result="${string%.*}" result="${result##*-}"
что приводит к resultcontaing substr3.
В Zsh вы можете сделать это за один шаг:, но в Bash это не работает.result=${${string%.*}##*-}
В Bash вы ограничены использованием расширений в правой части #или %, и это вам здесь не поможет, поскольку вам нужно удалить части как из начала, так и из конца строки.
В качестве альтернативы, если $stringне содержит символов новой строки, вы можете использовать
IFS=.- read -r a b c d <<< "$string"
и читать substr3с c.
В этом случае, в зависимости от оболочки и размера строки, содержимое $stringбудет либо сохранено во временном файле, либо пропущено через канал, который readбудет читать первую строку из и разделять ее в соответствии с $IFS.