2

I'm using following script for Shortest Sub-string Match in String handling.

filename="bash.string.txt"

echo ${filename#*.}

It gives following output.

string.txt

Here is an explanation of above example (Link: https://www.thegeekstuff.com/2010/07/bash-string-manipulation):

The above example deletes the shortest match of $substring from front of $string. In the first echo statement substring ‘*.’ matches the characters and a dot, and # strips from the front of the string, so it strips the substring “bash.” from the variable called filename.

Then I changed the code as below:

filename="bashshell.string.txt"

echo ${filename#*.}

I just extended the first string from bash. to bashshell. and expecting the output "bashshell.txt" according to explanation given above. But instead it gives me same output as first example.

i.e. string.txt

So do I misunderstood the concept? If yes than how it actually works?

3

So do I misunderstood the concept? If yes than how it actually works?

Yes the notation ${var#*.} is removing everything from the beginning of the string up to the character dot (.). It's doing what you asked of it, your pattern was star dot:

*.

So it will match everything up to the 1st dot from the start of the string, the one after the word bash.

bash.string.txt
    ^---------------- it's splitting here

Examples

$ str="bash.string.txt"
$ echo "${str#*.}"
string.txt

$ str="bash1.string.txt"
$ echo "${str#*.}"
string.txt

$ str="bash1.string1.txt"
$ echo "${str#*.}"
string1.txt

See when I put the 1 on the left side of the 1st .. This notation is truncating everything up to the 1st dot.

  • 1
    compared to ${str##*.} which will replace everything until the last dot. – pLumo Aug 7 '18 at 13:04
2

The tutorial's use of the word "substring" is slightly misleading. When using ${variable#pattern}, we're dealing with matching and deleting a prefix string (and with ${variable%pattern} a suffix string).

You removed the shortest prefix string matching *. from the two strings bash.string.txt and bashshell.string.txt. The result for both strings is the same, string.txt, because the pattern *. matches up to and including the first dot in the string.

The POSIX standard defines this particular parameter expansion as

${parameter#[word]}

Remove Smallest Prefix Pattern. The word shall be expanded to produce a pattern. The parameter expansion shall then result in parameter, with the smallest portion of the prefix matched by the pattern deleted. If present, word shall not begin with an unquoted #.

Had you wanted to get the result bashshell.txt, you would have had to remove the string .string or string. from the middle of the string. This could be done in two steps with standard parameter expansions:

suffix=${filename##*.}          # remove everything to the *last* dot
echo "${filename%%.*}.$suffix"  # remove everything from the first dot and add suffix

The ## and %% variations of the parameter expansion removes the longest matching prefix and suffix strings respectively.

Alternatively with bash:

echo "${filename/string./}"

This removes the (first occurrence of the) given string anywhere within the value of $filename.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.