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.
Related
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.
I am wrinting a sed invocation using a shell variable. The variable contains a path name with file name:
sed "file name is '$variable'"
...
variable=/path/path/file.txt
The problem is that I don't need the /path/path/ part. I need just file.txt part in output.
Also my path is dynamic so I am guessing that I need to search (somehow) in a string for a first slash from the ending. How do I do that?
You can use basename to do that:
basename /tmp/a.jpg
a.jpg
You can use the shell's variable substitution feature to remove parts matching a glob pattern:
$ variable=/path/path/file.txt
$ echo ${variable##*/} # Remove longest left part matching "*/"
file.txt
From the bash manual:
${parameter#word}
${parameter##word}
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 match-
ing 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}
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.
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.
I have a bash for loop like this:
for i in /long/path/filename*; do
echo ${i%filename*}/other/path/c01/{magic};
done
Now I would like to get {magic} replaced by the text matched by *
Maybe like this:
for i in /long/path/filename*; do
A=${i/\/long\/path\/filename/}
echo ${i%filename*}/other/path/c01/${A}
done
for i in /long/path/filename*;
do echo ${i%filename*}/other/path/c01/${i#/long/path/filename};
done
From man bash:
${parameter#word}
${parameter##word}
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.
I am a shell script newbie. I want to know the difference between
${var%pattern}
and
${var%%pattern}
Thanks
From man bash:
${parameter%word}
${parameter%%word}
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.
Here's an example of what the difference is:
$ VAR=abcdefabcdef
$ echo ${VAR%def*}
abcdefabc
$ echo ${VAR%%def*}
abc
Notice that there are two possible matches for def* at the end of $VAR: both "defabcdef" and just "def" match. With the "%" the shortest possible match for the pattern def* is deleted, so the trailing "def" is removed. With the "%%" the longest possible match is deleted, so "defabcdef" bites the dust.
From man bash:
${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.