Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to match until the last occurrence of a character in bash shell

I am using curl and cut on a output like below.

var=$(curl https://avc.com/actuator/info | tr '"' '\n' | grep - | head -n1 | cut -d'-' -f -1, -3)

Varible var gets have two kinds of values (one at a time).

HIX_MAIN-7ae526629f6939f717165c526dad3b7f0819d85b
HIX-R1-1-3b5126629f67892110165c524gbc5d5g1808c9b5

I am actually trying to get everything until the last '-'. i.e HIX-MAIN or HIX-R1-1.

The command shown works fine to get HIX-R1-1.

But I figured this is the wrong way to do when I have something something like only 1 - in the variable; it is getting me the entire variable value (e.g. HIX_MAIN-7ae526629f6939f717165c526dad3b7f0819d85b).

How do I go about getting everything up to the last '-' into the variable var?

like image 445
mo0206 Avatar asked Aug 19 '15 00:08

mo0206


People also ask

How do you find the last occurrence of a character in a string in Linux?

The strrchr() function finds the last occurrence of c (converted to a character) in string .

What does [- Z $1 mean in Bash?

$1 means an input argument and -z means non-defined or empty. You're testing whether an input argument to the script was defined when running the script. Follow this answer to receive notifications.

How do you find the last occurrence of a string in Unix?

The command is relatively simple. We start by finding the string we require using grep. Next, Grep will list all the string occurrences, and finally, we pipe the output to the tail and locate the last line of the output.

How to match last occurrence of a string in regex?

Regex: match last occurrence. The key to the solution is a so called “ negative lookahead “. A lookahead doesn’t consume characters in the string, but only asserts whether a match is possible or not. Of course the example is not taken from a real life scenario as it doesn’t matter which “foo” is matched as they’re all the same anyway.

How to find the last occurrence of a character in string?

If you like to find the exact index of the last occurrence of the character in the string, then you use the length function in the awk command. Although, I find the awk command to be much easier to find the occurrence of characters in string, you can use the sed command as well to do the same.

How to print string before and after the last occurrence in Linux?

If you want to print out the first part of the string before the last occurrence of the character in the string, then you can modify the sed argument to do just that. In Linux, brace notations are a useful way to print out variables. We can use the same to print out strings before and after the last occurrence of a character.

How to find the last occurrence of a string in AWK?

This works if you want to split the string using a separator character and want to do something with the rest of the string. If you like to find the exact index of the last occurrence of the character in the string, then you use the length function in the awk command.


3 Answers

This removes everything from the last - to the end:

sed 's/\(.*\)-.*/\1/'

As examples:

$ echo HIX_MAIN-7ae52 | sed 's/\(.*\)-.*/\1/'
HIX_MAIN
$ echo HIX-R1-1-3b5126629f67 | sed 's/\(.*\)-.*/\1/'
HIX-R1-1

How it works

The sed substitute command has the form s/old/new/ where old is a regular expression. In this case, the regex is \(.*\)-.*. This works because \(.*\)- is greedy: it will match everything up to the last -. Because of the escaped parens,\(...\), everything before the last - will be saved in group 1 which we can refer to as \1. The final .* matches everything after the last -. Thus, as long as the line contains a -, this regex matches the whole line and the substitute command replaces the whole line with \1.

like image 158
John1024 Avatar answered Oct 20 '22 07:10

John1024


You can use bash string manipulation:

$ foo=a-b-c-def-ghi
$ echo "${foo%-*}"
a-b-c-def

The operators, # and % are on either side of $ on a QWERTY keyboard, which helps to remember how they modify the variable:

  • #pattern trims off the shortest prefix matching "pattern".
  • ##pattern trims off the longest prefix matching "pattern".
  • %pattern trims off the shortest suffix matching "pattern".
  • %%pattern trims off the longest suffix matching "pattern".

where pattern matches the bash pattern matching rules, including ? (one character) and * (zero or more characters).

Here, we're trimming off the shortest suffix matching the pattern -*, so ${foo%-*} will get you what you want.

Of course, there are many ways to do this using awk or sed, possibly reusing the sed command you're already running. Variable manipulation, however, can be done natively in bash without launching another process.

like image 23
Jeff Bowman Avatar answered Oct 20 '22 07:10

Jeff Bowman


You can reverse the string with rev, cut from the second field and then rev again:

rev <<< "$VARIABLE" | cut -d"-" -f2- | rev

For HIX-R1-1----3b5126629f67892110165c524gbc5d5g1808c9b5, prints:

HIX-R1-1---
like image 3
higuaro Avatar answered Oct 20 '22 07:10

higuaro