I've come across this curious bash expression:
somestring=4.5.6
echo ${somestring%rc*}
For all that I can tell it just prints 4.5.6. So why would anybody use it?
I found it in this script (look for pkgver), so I hope I didn't miss any context which is necessary for this to work.
Source:
${string%substring} deletes shortest match of $substring from back of
$string.
The intention is to echo the numerical version only, without the rc* suffix for strings like:
somestring=4.5.6rc1
somestring=4.5.6rc23_whatever
UPDATE:
The better choice is to echo ${somestring%%rc*}.
Otherwise, the following might happen:
somestring=4.5.6rc1_rc2
echo ${somestring%rc*}
4.5.6rc1_
whereas:
echo ${somestring%%rc*}
4.5.6
It removes rc and any following characters (the *) from somestring. See, e.g., this answer.
This is known as parameter expansion.
From Bash manual:
${parameter%word}
${parameter%%word}
The word is expanded to produce a pattern just as in filename expansion. If the pattern matches a trailing portion of the expanded
value of parameter, then the result of the expansion is the 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.
Simply "${somestring%rc*}" is the string left by cutting rc* (* means anything after rc) from $somestring from right i.e rc* is matched in the string from right and then deleted and the resultant is the remaining string.
Related
I am new to shell script while i am going through some existing scripts. i am understanding below command
db2 -x some command | read
param
param=${param## };
param=${param%% };
Can any one please guide through this to understand
From the bash man page:
${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 patâ
tern (the ``##'' case) deleted. If parameter is # or *, the
pattern removal operation is applied to each positional parameâ
ter in turn, and the expansion is the resultant list. If paramâ
eter 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}
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 posiâ
tional 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 in conclusion, with your example in mind, param=${param## }; will remove the leading space from the variable param and ${parameter%%word} will remove the trailing space
We had to get the 'filename' and 'file extension' from a string
[sathish#oc Desktop]$ export FILE="filename.txt"
The following syntax works fine. However, we would like to understand how '##.' and '%.' works
[sathish#oc Desktop]$ echo ${FILE##*.}
txt
[sathish#oc Desktop]$ echo ${FILE%.*}
filename
Any help would be nice
Your starting point would be to read the bash manual, especially the section on Shell Parameter Expansion.
Some relevant excerpts:
${parameter#word}
${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.
${parameter%word}
${parameter%%word}
The word is expanded to produce a pattern just as in
filename expansion.
If the pattern matches a trailing portion of the expanded value of
parameter, then the result of the expansion is the 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:
"${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 code is from apache2 service starting script.
What does it mean?
SCRIPTNAME="${0##*/}"
It finds the name of the script being run, stripping out its directory. For instance if the script is /etc/init.d/httpd then this would set SCRIPTNAME=httpd.
$0, or ${0}, is the name of the script being executed. The ## operator is used to remove any leading string that matches the pattern */. * is a wildcard character so */ means "any string followed by a forward slash".
The effect of this is to remove any leading directory names from $0, leaving just the name of the script.
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.
The left side is easy: it assigns to the variable SCRIPTNAME.
The right side is more complicated:
$0 or ${0} is the name used to invoke the current shell or script.
${VAR##pattern} is the value of variable $VAR with the longest string that matches the pattern removed from the beggining (use one # for the shortest or %/%% to remove the end.
So your expression removes the start of the name used to call the script up to, and including, the last slash.
BTW, that is what the program basename does.
I have a portion of a bash script that is getting a filename without extension, but I'm trying to understand what is really going on here. What are the "%%"'s for? Can someone elaborate on what bash is doing behind the scenes? How can this technique be used on a general basis?
#!/bin/bash
for src in *.tif
do
txt=${src%%.*}
tesseract ${src} ${txt}
done
It gets rid of the filename extension (here: .tif), sample:
$ for A in test.py test.sh test.xml test.xsl; do echo "$A: ${A%%.*}"; done
test.py: test
test.sh: test
test.xml: test
test.xsl: test
from bash manual:
${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.
Here's output from the bash man page
${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 pat-
tern (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.
Apparently bash has several "Parameter Expansion" tools which include:
Simply substituting the value...
${parameter}
Expanding to a sub-string...
${parameter:offset}
${parameter:offset:length}
Substitute the length of the parameters value...
${#parameter}
Expanding upon a match at the beginning of the parameter...
${parameter#word}
${parameter##word}
Expanding upon a match at the end of the parameter...
${parameter%word}
${parameter%%word}
Expands the parameter to find and replace a string...
${parameter/pattern/string}
These are my interpretation of the parts I think I understand from this section of the man pages. Let me know if I missed something important.
Check out "Parameter Expansion" in the bash man pages. That syntax expands the $src variable deleting stuff that matches the .* pattern from it.
It's a string removal operation in the format: ${str%%substr}
Where str is the string you are operating on, and substr is the pattern to match. It looks for the longest match of substr in str, and removes everything from that point on.