I have this function:
#! /usr/bin/env bash
function underline() {
U="${1//?/${2:--}}"
echo -e "\n$1\n${U:0:${#1}}\n"
}
underline "$1" "^-v-"
will work as expected:
$ ./u.sh "This is all you're going to see"
This is all you're going to see
^-v-^-v-^-v-^-v-^-v-^-v-^-v-^-v
It does what you expect. Originally it assumed that the underline character was just that, 1 character.
For "fun", I extended it to move from a single character underline to a repeating string underline (why? ... well ... because I can I suppose ... almost zero practical value in this exercise!).
And so, being the "let's make this so difficult that you need to write 2 pages of documentation to explain what's going on" sort of guy, I was wondering if the function could be written as a single line. And I don't mean:
function underline() { U="${1//?/${2:--}}"; echo -e "\n$1\n${U:0:${#1}}\n"; }
I don't think you can combine bash's variable search/replace with substring which is what is required.
I'm aware that this will work happily in zsh:
#! /usr/bin/env zsh
function underline() {
echo -e "\n$1\n${${1//?/${2:--}}:0:${#1}}\n"
}
underline $1 "^-v-"
e.g.
$ ./u.sh "This is all you're going to see"
This is all you're going to see
^-v-^-v-^-v-^-v-^-v-^-v-^-v-^-v
but not capable of this in bash (it seems).
CodePudding user response:
No, you cannot combine those in a single parameter expansion in bash. But this single printf
(a builtin in bash) should do the trick:
underline() { printf '%s\n%.*s\n' "$1" ${#1} "${1//?/${2:--}}"; }
underline "This is all you're going to see" "^-v-"
outputs
This is all you're going to see
^-v-^-v-^-v-^-v-^-v-^-v-^-v-^-v