This question already has answers here:
What is the meaning of the ${0##...} syntax with variable, braces and hash character in bash?
(4 answers)
Closed 2 years ago.
I'm looking through a bash script I've inherited and come across this line:
local n=${x##*wlan}
I've never seen this syntax, I know that local means a variable in the scope of a function, I'm just unsure about the ${*##} part and it's pretty tricky to google that syntax.
It removes everything up to the last wlan match in the $x variable.
asldkjflkasjdfljsdwlanalsdkjfkajsdflswlanasdlfaksdlfj
# ^^^^ ^^^^
# | |--->
# | ${x##*wlan}
# ${x#*wlan}
See an example:
$ x="hello1hello2hello3"
$ echo "${x##*hello}" # with two ## it matches the longest matching pattern
3
$ echo "${x#*hello}" # with one # it matches the shortest matching pattern
1hello2hello3
Graphically:
hello1hello2hello3
# ^
# ^ ${x##*hello}
# ${x#*hello}
From Bash Reference Manual - 3.5.3 Shell Parameter Expansion:
${parameter##word}
The word is expanded to produce a pattern just as in filename
expansion (see Filename Expansion). If the pattern matches the
beginning of the expanded value of parameter, then the result of the
expansion is the expanded value of parameter with the shortest
matching pattern (the ‘#’ case) or the longest matching pattern (the
‘##’ case) deleted. If parameter is ‘#’ or ‘’, the pattern removal
operation is applied to each positional parameter in turn, and the
expansion is the resultant list. If parameter is an array variable
subscripted with ‘#’ or ‘’, the pattern removal operation is applied
to each member of the array in turn, and the expansion is the
resultant list.
It's called parameter substitution/expansion, see here for more information.
Your example removes the longest match of *wlan from the beginning of the variable $x.
Related
This question already has an answer here:
What is the meaning of `//` in Bash parameter expansions?
(1 answer)
Closed last year.
I am currently moving our shell/bash scripts from a jenkinsfile to groovy scripts that are stored in methods but still execute as sh scripts.
The issue i have is with variables containing // /_
exmaple:
${VARIABLE_NAME// /_}
I cannot find what // /_ exactly does when supplied like this in a variable.
I need to find another way to do this because when moved to Groovy methods, it causes formating issues where escaping doesnt work properly.
It will replace all spaces with underscores.
Consider the following example:
$ var='hello world john doe'
$ echo "${var// /_}"
hello_world_john_doe
$
${parameter/pattern/string}
The pattern is expanded to produce a pattern just as in filename expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. The match is performed according to the rules described below (see Pattern Matching). If pattern begins with ‘/’, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with ‘#’, it must match at the beginning of the expanded value of parameter. If pattern begins with ‘%’, it must match at the end of the expanded value of parameter. If string is null, matches of pattern are deleted and the / following pattern may be omitted. If the nocasematch shell option (see the description of shopt in The Shopt Builtin) is enabled, the match is performed without regard to the case of alphabetic characters. If parameter is ‘#’ or ‘’, the substitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with ‘#’ or ‘’, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.
Copied from: https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html with my emphasize on how / and // differences.
This question already has answers here:
Syntax with pound and percent sign after shell parameter name [duplicate]
(2 answers)
Closed 4 years ago.
Can anyone explain the following bash snippet?
for i in $(seq 1 1 10)
do
VAR=${2%?}$i
break;
done
It removes the trailing character from $2 (second positional parameter) and concatenates that value with $i
example:
$ v1="myvalue1x"
$ v2="myvalue2"
$ combined="${v1%?}$v2"
$ echo $combined
myvalue1myvalue2
For more info how the substitution works you can check the Parameter Expansion section of the bash manual
See the bash man page, section parameter expansion:
${parameter%word}
${parameter%%word}
Remove matching suffix pattern. The word is expanded to produce a
pattern just as in pathname expansion. If the pattern matches a
trailing portion of the expanded value of parameter, then the
result of the expansion is the expanded value of parameter with the
shortest matching pattern (the ``%'' case) or the longest matching
pattern (the ``%%'' case) deleted. If parameter is # or *, the
pattern removal operation is applied to each positional parameter
in turn, and the expansion is the resultant list. If parameter is
an array variable subscripted with # or *, the pattern removal
operation is applied to each member of the array in turn, and the
expansion is the resultant list.
Since ? matches a single character, the trailing character is removed from the second argument of the script.
This question already has answers here:
"${0%/*}" and "${0##*/}" in sh [duplicate]
(2 answers)
Closed 2 years ago.
Please explain the following syntax:
i##*.
i%.*
I understand what it's doing, but I want to know the general pattern (why/how is it doing so).
Code where it appears:
#!/bin/bash
recursive_name_change()
{
cd "$1"
for i in *
do
#echo "${i##*.}"
if [ -d "$i" ]
then
recursive_name_change "$i"
elif [ "${i##*.}" = "cpp" ]
then
new_name=${i%.*}".c"
mv "$i" "$new_name"
fi
done
cd ../
}
recursive_name_change .
Someone please also suggest, where can I find these peculiar syntax forms from?
See Parameter Expansion in man bash:
${parameter#word}
${parameter##word}
Remove matching prefix pattern. The word is expanded to produce a pattern just
as in pathname expansion. If the pattern matches the beginning of the value of
parameter, then the result of the expansion is the expanded value of parameter
with the shortest matching pattern (the # case) or the longest matching pattern (the ## case) deleted. If parameter is # or *, the pattern removal
operation is applied to each positional parameter in turn, and the expansion is
the resultant list. If parameter is an array variable subscripted with # or *,
the pattern removal operation is applied to each member of the array in turn,
and the expansion is the resultant list.
${parameter%word}
${parameter%%word}
Remove matching suffix pattern. The word is expanded to produce a pattern just
as in pathname expansion. If the pattern matches a trailing portion of the
expanded value of parameter, then the result of the expansion is the expanded
value of parameter with the shortest matching pattern (the % case) or the
longest matching pattern (the %% case) deleted. If parameter is # or *,
the pattern removal operation is applied to each positional parameter in turn,
and the expansion is the resultant list. If parameter is an array variable
subscripted with # or *, the pattern removal operation is applied to each mem-
ber of the array in turn, and the expansion is the resultant list.
In short, # removes the pattern from the left, % from the right, doubling the symbol makes the matching greedy. (Mnemonic: # is to the left of % on most keyboards).
Look for the section "Substring removal" in this manual:
${string##substring}
Deletes longest match of $substring from front of $string.
${string%substring}
Deletes shortest match of $substring from back of $string.
This question already has answers here:
Syntax with pound and percent sign after shell parameter name [duplicate]
(2 answers)
Closed 3 years ago.
I have a bash script and I see in the code
${variable#!}
what it means?
thanks a lot
it removes the leading ! from the value of the variable.
an example would be:
kent$ foo='!!hello'
kent$ echo ${foo#!}
!hello
See http://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameter-Expansion
${parameter#word}
The word is expanded to produce a pattern just as in filename expansion. If the pattern matches the beginning of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern. If parameter is ‘#’ or ‘’, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with ‘#’ or ‘’, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.
So, if $variable begins with !, it will return its content without the first !. If not, it will return $variable.
demo:
var="!some!some!"
echo ${var#!}
prints
some!some!
This question already has answers here:
Syntax with pound and percent sign after shell parameter name [duplicate]
(2 answers)
Closed 3 years ago.
Here is an example to get different parts of a filename
bash-3.2$ pathandfile=/tmp/ff.txt
bash-3.2$ filename=$(basename $pathandfile)
bash-3.2$ echo $filename
ff.txt
bash-3.2$ echo ${filename##*.}
txt
bash-3.2$ echo ${filename%.*}
ff
I was wondering what does ## and % mean in the patterns. How is the patten matching working?
Thanks and regards!
The manpage for bash says:
${parameter#word}
${parameter##word}
Remove matching prefix pattern. The word is expanded to produce a pattern just as
in pathname expansion. If the pattern matches the beginning of the value of parameter, then the result of the expansion is the expanded value of parameter with the
shortest matching pattern (the # case) or the longest matching pattern (the
## case) deleted. If parameter is # or *, the pattern removal operation is
applied to each positional parameter in turn, and the expansion is the resultant
list. If parameter is an array variable subscripted with # or *, the pattern
removal operation is applied to each member of the array in turn, and the expansion
is the resultant list.
${parameter%word}
${parameter%%word}
Remove matching suffix pattern. The word is expanded to produce a pattern just as
in pathname expansion. If the pattern matches a trailing portion of the expanded
value of parameter, then the result of the expansion is the expanded value of
parameter with the shortest matching pattern (the % case) or the longest matching pattern (the %% case) deleted. If parameter is # or *, the pattern removal
operation is applied to each positional parameter in turn, and the expansion is the
resultant list. If parameter is an array variable subscripted with # or *, the
pattern removal operation is applied to each member of the array in turn, and the
expansion is the resultant list.
From http://tldp.org/LDP/abs/html/string-manipulation.html:
${string##substring}
Deletes longest match of $substring from front of $string.
and
${string%substring}
Deletes shortest match of $substring from back of $string.
See http://tldp.org/LDP/abs/html/string-manipulation.html.
${string##substring}
Deletes longest match of $substring from front of $string.
${string%substring}
Deletes shortest match of $substring from back of $string.