8

I have a String like this

//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf 

and want to get last part of

00000000957481f9-08d035805a5c94bf

7 Answers 7

21

Let's say you have

text="//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf"

If you know the position, i.e. in this case the 9th, you can go with

echo "$text" | cut -d'/' -f9

However, if this is dynamic and your want to split at "/", it's safer to go with:

echo "${text##*/}"

This removes everything from the beginning to the last occurrence of "/" and should be the shortest form to do it.

For more information on this see: Bash Reference manual

For more information on cut see: cut man page

Sign up to request clarification or add additional context in comments.

6 Comments

${text##*/} is not only shortest, but also much more efficient than the echo | cut approach. One gotcha -- you need to add quotes; otherwise, the text can be string-split rejoined by echo; to see why that can cause bugs, try running this code with IFS=- or, worse, IFS=0.
...so, echo "${text##*/}", with the quotes, is the safe and efficient approach.
And what if I want to take the first part? What's the name? How can I search online to find variants?
"First part" really depends on the form the string is set up and what you define it to be. To e.g. grab the "ABC" in my example, echo $text | cut -d'/' -f3 will provide it.
I updated my answer to include the quotes. Thanks for catching this.
|
7

The tool basename does exactly that:

$ basename //ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf  
00000000957481f9-08d035805a5c94bf

Comments

3

In case you want more than just the last part of the path, you could do something like this:

  echo $PWD | rev | cut -d'/' -f1-2 | rev

Comments

2

I would use bash string function:

$ string="//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf"

$ echo "${string##*/}"
00000000957481f9-08d035805a5c94bf

But following are some other options:

$ awk -F'/' '$0=$NF' <<< "$string"
00000000957481f9-08d035805a5c94bf

$ sed 's#.*/##g' <<< "$string"
00000000957481f9-08d035805a5c94bf

Note: <<< is herestring notation. They do not create a subshell, however, they are NOT portable to POSIX sh (as implemented by shells such as ash or dash).

6 Comments

I'd worry more about portability to POSIX sh (as implemented by modern shells such as ash and dash) than portability to Bourne (which predates it by decades). If we had to provide disclaimers whenever something wasn't portable to Bourne, we wouldn't have $(( 1 + 1 )) or "$(some-command "$(other-command)")" either.
...really, for all that bash's name says "Bourne Again", it's more of an enhanced derivative of the Korn shell (an early version of which the POSIX sh standard was loosely based on). The point of which being -- Bourne is really, really ancient.
Thanks @CharlesDuffy for the insight. My experience with *nix is nothing compared to yours. Ill reference your comments in the answer. Thanks again.
No worries. If I'm going to be a pedant, least I can do is try to be a helpful one. :)
@CharlesDuffy Your pedantic nature is an excellent source for learning.
|
1

You can use this BASH regex:

s='//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf'
[[ "$s" =~ [^/]+$ ]] && echo "${BASH_REMATCH[0]}"
00000000957481f9-08d035805a5c94bf

Comments

1

This can be done easily in awk:

string="//ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf"

echo "${string}" | awk -v FS="/" '{ print $NF }'

Use "/" as field separator and print the last field.

Comments

0

You can try this...

echo //ABC/REC/TLC/SC-prod/1f9/20/00000000957481f9-08d035805a5c94bf |awk -F "/" '{print $NF}'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.