19

I found how to print everything before a slash, however I need to print everything after a slash. I have a string like blablabal/important and I need to print only important. How should I modify the line below to get printed everything after a slash and not before?

sed 's:/[^/]*$::'
6
  • You need to print everything after the first slash, or everything after the last slash?
    – Kira
    Dec 5, 2015 at 16:30
  • @Kira Looks like last slash to me with $ in the regex.
    – Sly
    Dec 5, 2015 at 16:30
  • I have only one column in a test file. Each row is a string where slash appears only once.
    – Iris Pader
    Dec 5, 2015 at 16:31
  • 6
    Use the right tool for this job: cut -d/ -f2- <infile Dec 5, 2015 at 18:21
  • 1
    @MichaelHoffmann - isn't the reason obvious? i.e. cut was designed for this job (extracting one or more fields) while sed is a "general purpose tool" (so not optimized for this task) ; also, regex is expensive: if you had to process millions of records with hundreds of fields each you'd see the difference... May 23, 2019 at 19:02

6 Answers 6

30

Just delete everything until the last slash:

$ echo "blablabal/important" | sed 's:.*/::'
important

It also works with multiple slashes:

$ echo "blablabal/not/ver/interesting/important" | sed 's:.*/::'
important
3
  • 2
    sed 's/.*\///' may be more POSIX-standard.
    – Soping Lee
    Oct 29, 2021 at 9:07
  • 1
    @SopingLee thanks, but no, this is POSIX. See pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html: "Any character other than <backslash> or <newline> can be used instead of a <slash> to delimit the BRE and the replacement."
    – terdon
    Oct 29, 2021 at 9:34
  • 1
    @Niing please ask a separate question, that is a different issue.
    – terdon
    Jun 15, 2022 at 14:46
21

It looks like the other answers are assuming that you have multiple lines of data in a file, which are all to be processed. In this case sed or awk (or possibly cut) would be the best tools for processing all the lines in one go.

However, if you just have one line in a shell variable (assuming you're using bash), you can use shell expansions to achieve the desired result, without having to spawn utilities in external processes:

$ var="interesting/bla/blablabal/important"
$ 
$ # everything after the first slash:
$ echo "${var#*/}"
bla/blablabal/important
$ # everything after the last slash:
$ echo "${var##*/}"
important
$ # everything before the first slash:
$ echo "${var%%/*}"
interesting
$ # everything before the last slash:
$ echo "${var%/*}"
interesting/bla/blablabal
$ 

Alternatively, I assume your slash-separated strings are file paths. If that is the case, you can use dirname and basename to get the path and filename components:

$ # everything before the last slash:
$ dirname "$var"
interesting/bla/blablabal
$ # everything after the last slash:
$ basename "$var"
important
$ 
2
  • How can I get the rest of the second last slash?
    – Jin Kwon
    Nov 10, 2022 at 5:26
  • 1
    @JinKwon Are you referring to the "blablabal" substring in the above example? If so you could do basename $(dirname "$var") Nov 10, 2022 at 17:24
15

Since you mentioned in your comment that the file only has one slash, why not just use awk?

Example:

 ❱ echo "blablabal/important" | awk -F'/' '{print $1}'
blablabal
 ❱ echo "blablabal/important" | awk -F'/' '{print $2}'
important
2
  • 1
    This only prints the second part in a string with multiple slashes. Well, unfortunately that's what the asker wants… Dec 5, 2015 at 22:13
  • Indeed. No reason to overcomplicate it with a sed replacement if there's only two results.
    – Sly
    Dec 5, 2015 at 22:17
1

This sould work:

echo "blablabal/important" | sed 's:[^/]*/\(.*\):\1:'

The first part [^/]*, matches everything BUT a slash, then we have a literal slash /, and a "matches everything" .* inside escaped parenthesis \(.*\). The escaped parenthesis are there to "save" the matching result, meaning that it will contain everything after the first slash in this case. The \1 refer to the first matched group, in this case we only have one group, because there is only one \(...\) pair.

In sed, the character you type after the s will be the delimiter. It is a common practice to use / as delimiter, but is this case it is easier to use something else, although it would be possible to use a slash too.

3
  • Yes, there are like 100 other ways to do that. I think terdon's answer might be the shortest with sed. cut would also be a good answer for this specific case.
    – Kira
    Dec 5, 2015 at 19:05
  • you guys do exactly opposite things though - you get the first, he gets all.
    – mikeserv
    Dec 5, 2015 at 19:05
  • True, that's why I've asked OP if he wanted everything after the first or last slash, but as there is only one slash per line in his case, it won't make any difference.
    – Kira
    Dec 5, 2015 at 19:07
1
sed -et -e's|/|&\n|;//D' <in >out

...will print everything after the first slash on any line which contains one, or else print any other unmodified. If you drop the // it will only print lines it modifies.

You may need to use a literal \newline in place of the n in the \n escape though, depending on your sed version.

Also, if you specify an occurrence count...

sed -et -e's|/|&\n|num;/\n/D'

...you can delete up to the numth slash on a line without affecting any line which doesn't contain at least num slashes.

0

grep solution:

$ echo "blablabal/important" | grep -oP "/\K.*"
important

\K drops the matched string in output

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .