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##*-}"
что приводит к result
containg substr3
.
В Zsh вы можете сделать это за один шаг:, но в Bash это не работает.result=${${string%.*}##*-}
В Bash вы ограничены использованием расширений в правой части #
или %
, и это вам здесь не поможет, поскольку вам нужно удалить части как из начала, так и из конца строки.
В качестве альтернативы, если $string
не содержит символов новой строки, вы можете использовать
IFS=.- read -r a b c d <<< "$string"
и читать substr3
с c
.
В этом случае, в зависимости от оболочки и размера строки, содержимое $string
будет либо сохранено во временном файле, либо пропущено через канал, который read
будет читать первую строку из и разделять ее в соответствии с $IFS
.