bashparameter-expansion

Extract substring from string after third last occurrence of underscore


I have a string in Linux shell. This string contains underscores in it.

I want to extract a substring from the string.

I want to extract the substring after the third occurrence of an underscore, counted from the end of the string.

file_name='email_Tracking_export_history_2018_08_15'
string_name="${file_name#*_*_*_}"
file_name2='email_Tracking_export_2018_08_15'
string_name2="${file_name2#*_*_*_}"

echo "$string_name"
echo "$string_name2"

The result

history_2018_08_15
2018_08_15

As you see, string_name="${file_name#*_*_*_}" is not working properly.

Desired result:

2018_08_15
2018_08_15

How can I achieve my desired result?


Solution

  • You can do it in a single step, but it's a bit convoluted. After setting the filename

    file_name='email_Tracking_export_history_2018_08_15'
    

    we get the substring that contains everything except what we want to have in the end:

    $ echo "${file_name%_*_*_*}"
    email_Tracking_export_history
    

    This is almost what we want, just an underscore missing, so we add that:

    $ echo "${file_name%_*_*_*}_"
    email_Tracking_export_history_
    

    Now we know what we have to remove from the beginning of the string and insert that into the ${word#pattern} expansion:

    $ echo "${file_name#"${file_name%_*_*_*}_"}"
    2018_08_15
    

    or we assign it to a variable for further use:

    string_name=${file_name#"${file_name%_*_*_*}_"}
                  └───┬───┘ │  └───┬───┘ └─┬──┘  │
                 outer word │  inner word  └─────┼──inner pattern
                            └───outer pattern────┘
    

    And analogous for the second string.