Parameter expansion with double caret ^^
Asked Answered
E

2

8

In the following block of code, how are line# 3 and 4 evaluated?

for f in "${CT_LIB_DIR}/scripts/build/debug/"*.sh; do
    _f="$(basename "${f}" .sh)"
    _f="${_f#???-}"
    __f="CT_DEBUG_${_f^^}"
done
Euridice answered 11/7, 2019 at 23:24 Comment(1)
Next time you can remove the ìf..fi` block (not relevant) or debug yourself by adding echo "$f -> ${_f} -> ${__f}".Baxley
H
16
${PARAMETER#PATTERN}

Substring removal

This form is to remove the described pattern trying to match it from the beginning of the string. The operator "#" will try to remove the shortest text matching the pattern, while "##" tries to do it with the longest text matching.

STRING="Hello world"
echo "${STRING#??????}"
>> world

${PARAMETER^}
${PARAMETER^^}
${PARAMETER,}
${PARAMETER,,}

These expansion operators modify the case of the letters in the expanded text.

The ^ operator modifies the first character to uppercase, the , operator to lowercase. When using the double-form (^^ and ,,), all characters are converted.

Example:

var="somewords"
echo ${var^^}
>> SOMEWORDS

See more information on bash parameter expansion

Highwrought answered 11/7, 2019 at 23:32 Comment(2)
Just for reference to anyone else reading this, replacing # and ## with % and %% (respectively) does the same thing, but from the end.Selway
Also, ~ and ~~ can be used to flip the case (analogous to ^, ^^, ,, ,,)Selway
B
1

The lines 2,3,4 are for constructing a variable name

(2)    _f="$(basename "${f}" .sh)"
(3)    _f="${_f#???-}"
(4)    __f="CT_DEBUG_${_f^^}"

In line 2 the path is removed and also the .sh at the end.
In line 3 the first 4 characters are removed when the fourth character is a -.
In line 4 it is appended to a string and converted to uppercase.
Let's see what happens to a/b/c.sh and ddd-eee.sh

       a/b/c.sh       ddd-eee.sh
(2)    c              ddd-eee
(3)    c              eee
(4)    CT_DEBUG_C     CT_DEBUG_EEE

Steps 2,3,4 can be replaced by 1 line:

__f=$(sed -r 's#(.*/)*(...-)?(.*).sh#CT_DEBUG_\U\3#' <<< "$f")

EDIT: First I had (...-)*, that would fail with aaa-bbb-c.sh: bbb- would be removed too!

In this case you don't have the variable _f what is used later in the code, so you might want 2 lines:

_f=$(sed -r 's#(.*/)*(...-)?(.*).sh#\3#' <<< "$f")
__f="CT_DEBUG_${_f^^}"
Baxley answered 12/7, 2019 at 8:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.