Reputation: 17928
I have the following function defined in bash:
function print_revision {
printf "Revision %s (%s)\n%s\n\n" "$1" "$(date --utc +%d.%m.%Y,\ %H:%M\ UTC)" \
"----------------------------------------"
}
I also have a variable, $CHANGES
with some text in it. What I would need to do is prepend the string printed in print_revision
to the $CHANGES
variable.
I've tried the following but it doesn't seem to work:
CHANGES="$(print_revision $CURRENT_SHORT_REVISION)"$CHANGES
It prepends everything from print_revision
but it goes through the last two newline characters, concatenating the contents of $CHANGES
right after the -----
part.
How can I achieve what I need?
Upvotes: 1
Views: 188
Reputation: 295815
Don't use command substitution here.
printf -v var_name format_string arg1 arg2 ...
...stores the output of the printf directly into var_name
, without any subshell involved (more efficient!), and no command substitution (no stripping of trailing newlines!)
Thus:
print_revision_to() {
printf -v "$1" \
"Revision %s (%s)\n%s\n\n" \
"$2" \
"$(date --utc +%d.%m.%Y,\ %H:%M\ UTC)" \
"----------------------------------------"
}
# ...thus, to put a header for revision 13 into "$changes", you'd run...
print_revision_to changes 13
...or, if you want to do this all at once...
prepend_revision_header_to() {
printf -v "$1" \
"Revision %s (%s)\n%s\n\n%s" \
"$2" \
"$(date --utc +%d.%m.%Y,\ %H:%M\ UTC)" \
"----------------------------------------"
"${!1}"
}
# ...thus, to modify the existing value of "$changes" by putting a header
# at the beginning, you'd run...
prepend_revision_header_to changes 13
Upvotes: 4
Reputation: 532303
The simplest fix is to just print the current value of $CHANGES
inside the command substitution:
CHANGES="$(print_revision $CURRENT_SHORT_REVISION; echo "$CHANGES")"
Upvotes: 1
Reputation: 241931
One possibility would be to pass the existing value (if any) into the function:
prepend_revision() {
printf "Revision %s (%s)\n%s\n\n%s" \
"$1" "$(date --utc +%d.%m.%Y,\ %H:%M\ UTC)" \
"----------------------------------------" "$2"
}
CHANGES=$(prepend_revision "$CURRENT_SHORT_REVISION" "$CHANGES")
Note that if you call prepend_revision
with only one argument, the output is exactly the same as the existing print_revision
function, so it can be used either to create or prepend.
Upvotes: 1
Reputation: 107879
Command substitution strips off newlines at the end of the string. The typical use case is that the output ends with a newline and is either going to be printed with another newline or concatenated with another string to make up a single line (e.g. echo $(echo part1)$(echo part2)
).
If you can't or don't want to change the print_revision
function, print a non-newline character after it, then strip it off.
new_revision=$(print_revision $CURRENT_SHORT_REVISION; echo a); new_revision=${new_revision%a}
CHANGES=$new_revision$CHANGES
Alternatively, put as many newlines as you want in the concatenation.
CHANGES="$(print_revision $CURRENT_SHORT_REVISION)
$CHANGES"
Upvotes: 2
Reputation: 1919
$ man bash
...
Command Substitution
...
Bash performs the expansion by executing command and replacing the com‐
mand substitution with the standard output of the command, with any
trailing newlines deleted.
Hence the use of $(...) is removing the trailing newlines.
If you want to keep a separate print_revision function then one approach would be to avoid trailing newlines in its output by appending a sentinel in print_revision, then stripping that off when you use it:
function print_revision {
printf "Revision %s (%s)\n%s\n\n___" ...
}
REVISION="$(print_revision $CURRENT_SHORT_REVISION)"
CHANGES="${REVISION%___}$CHANGES"
Upvotes: 1