Follow

This one is super free! It is not a programming problem so much as a BASH problem.

Using bash parameter expansion only gnu.org/software/bash/manual/h

Given an arbitrarily long path, such as "/head/shoulders/knees/and/toes/eyes/ears/mouth" stored in a variable $TEMP construct a parameter expansion to render only the last two subdirectory and filename like "eyes/ears/mouth" such that you can simply offer the command "echo ${TEMP<stuff goes in here>}"

And yes I do know how much easier it is to do with grep, sed, python, perl, awk <insert your favorite alternate solution here> can do it better and easier. This is a real world problem, and someone on Reddit pointed me in the right direction.

Solution (with caveat) 

@Absinthe

The following _technically_ satisfies your requirements; in that I only replace the stuff in brackets from your example and doesn't use anything but parameter expansion.

However, there's a serious limitation I haven't figured out how to work around - it relies on knowing the name of the variable $TEMP. As stated the problem permits this, but that means I can't save my answer in a variable and reuse it like echo ${TEMP1<foo>}; echo ${TEMP2<foo>} without modifying <foo> in between.

echo ${TEMP#${TEMP%/**/**/**}}

Solution (with caveat) 

@khird close but that one still has the leading / on the output. Also, I don't think you need **, * will be sufficient. You are close :)

Solution (with caveat) 

@Absinthe

For some reason I had the idea the spec wanted the leading slash. This gets it without, but has the same caveat as the above.

echo ${TEMP#${TEMP%%+([^/])/+([^/])/+([^/])}}

Solution (with caveat) 

@khird
That gives the final path without any '/' at all ..

You were closer with the previous one

Solution (with caveat) 

@Absinthe Given your example where $TEMP="/head/shoulders/knees/and/toes/eyes/ears/mouth", it returns exactly "eyes/ears/mouth". Do you have a test case where it doesn't work?

Solution (with caveat) 

@khird I just typed this in and got this:

$ TEMP="/head/shoulders/knees/and/toes/eyes/ears/mouth"
$ echo ${TEMP#${TEMP%%+([^/])/+([^/])/+([^/])}}
eyes ears mouth

Solution (with caveat) 

@Absinthe Perhaps you have a bug in your version of Bash? That statetment involves two parameter manipulations - the inner removing a suffix and the outer removing a prefix. Neither of them should perform a character-replacement to print ' ' instead of '/'.

It works perfectly in Bash 4.3.11.

Solution (with caveat) 

@khird interestnig, it works at work, on 5.0.3 I will have to check the laptop again when I get home.

Consider this:
echo "${TEMP#${TEMP%/*/*/*}/}"

Solution (with caveat) 

@khird so I tried it in a new terminal window and it works. I tried it in the previous window and it still does it without the /'s funny that, but meh, almost with I could do that on purpose. But, anyway it works. Well done!

Solution (with caveat) 

@khird you know the name of the variable because you are working with it... I think the original problem was based on something like

for I in $(ls SOMETHING) ; do SOMETHING with ${I <stuf>)

I just stored a bunch of crap in the $TEMP variable to play with it and not make the problem too complex.

Solution (with caveat) 

@Absinthe

In that context, you know the name of the variable. A solution where you don't need to know the name of the variable would be more useful in other circumstances, however.

For example, let's say I am allowed to execute but not modify a script which reads the pattern from a file or environment variable or something. If the permissions of that file or variable are insufficiently restrictive, I can manipulate the effect of the script by overwriting that pattern with my own. But if the script is going to make multiple calls like do_something_with ${TEMP1<foo>}; do_something_with ${TEMP2<foo>}; then I would need a version of <foo> that is independent of the name of the variable.

Solution (with caveat) 

@khird is that possible within the constraints?

Sign in to participate in the conversation
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.