What's meaning about this in shell? - shell

Does someone knows the meaning of the code below?
#!/bin/sh
files=`find -name *.conifg`
for i in $files
do
name=${i#*/}
dir=${name%/*}
done
I don't understand the two lines:
name=${i#*/}
dir=${name%/*}
What's the meaning of "#/" and "%/"? Thanks.

This is called Shell Parameter Expansion.
Let's do a test to see its behaviour:
$ mypath="this/is/my/path"
$ echo ${mypath#*/}
is/my/path
$ echo ${mypath%/*}
this/is/my
So
name=${i#*/} -> gets everything from first slash in $i variable.
dir=${name%/*} -> gets everything up to last slash in $name variable.
Taken from the resource:
${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). 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}
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) 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.

Related

What is the meaning of `//` in Bash parameter expansions?

What does //,/ mean in this command?
echo ${foo//,/}
From the bash(1) man page (http://linux.die.net/man/1/bash):
${parameter/pattern/string}
Pattern substitution. The pattern is expanded to produce a pattern just as in pathname expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. 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 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.
That is, ${something//,/} is expanded to the $something with all the occurrences of , removed.

Stripping characters from a Bash variable

I am attempting to write a bash script (poorly) and need assistance in stripping characters from a variable.
variable is defined as $managementipmask= 111.111.111.111/24
I need to strip the /24 from the end of the variable.
Thanks in advance.
Use parameter expansion to remove everything from the first /:
$ k="111.111.111.111/24"
$ echo "${k%%/*}"
111.111.111.111
See this resource on parameter expansion for additional details:
http://mywiki.wooledge.org/BashGuide/Parameters#Parameter_Expansion
${parameter%pattern}
The 'pattern' is matched against the end of 'parameter'. The result is
the expanded value of 'parameter' with the shortest match deleted.
${parameter%%pattern}
As above, but the longest match is deleted.
So you can delete from the last / using a single %:
$ k="111.111.111.111/24/23"
$ echo "${k%/*}"
111.111.111.111/24
Another way:
k="111.111.111.111/24"
echo "${k/%\/24/}"
It replaces last /24 with empty string.
From Bash Manual:
${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. 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 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.

SED script called from BASH: How can I shorten variable path in output?

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.

clarification with a shell script

Can somebody explain how echo "${PWD/#$HOME/~}" would print ~ in case the PWD evaluates to $HOME. Never read about such replacement using echo. What is going on here?
It is not echo it is your shell makes Parameter Expansion using ${parameter/pattern/string} syntax:
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. 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 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.
It doesn't look like POSIX supports it.
In your case, it replaces the value of $HOME envvar (not the string '$HOME' literally) with ~ in the output if PWD envvar starts with it.

Get the value before decimal point

I am writing a Bash script. I have a variable in it which is a float value. For example:
x=2099.2
I need the value before decimal point, i.e, only 2099.
You can use the following shell parameter expansion:
${x%%.*}
This removes everything from the first dot.
See it live:
$ v=203.4
$ echo ${v%%.*}
203
$ v=2.3.4
$ echo ${v%%.*}
2
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. 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 longest matching pattern 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.

Resources