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

I use curl and cut for output, as shown below.

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

A varied var gets two types of values ​​(one at a time).

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

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

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

But I realized that this is the wrong way to do it when I have something like only 1 - in a variable; it gets me all the variable value (e.g. HIX_MAIN-7ae526629f6939f717165c526dad3b7f0819d85b ).

How do I get everything to the last '-' in var variable?

+7
bash regex shell grep
source share
4 answers

This removes everything from the last - and ending with:

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

As an example:

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

How it works

The subst substitute command is of the form s/old/new/ , where old is a regular expression. In this case, the regular expression \(.*\)-.* . This works because \(.*\)- is greedy: it will match everyone to the last - . Because of the escaped pairs \(...\) everything until the last - will be saved in group 1, which we can call \1 . Final .* Matches all after - . Thus, if the string contains - , this regular expression matches the entire string, and the substitute command replaces the entire string with \1 .

+10
source share

You can use bash string manipulation :

 $ foo=abc-def-ghi $ echo "${foo%-*}" abc-def 

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

  • #pattern truncates the shortest prefix matching "pattern".
  • ##pattern disables the longest prefix matching the "pattern".
  • %pattern truncates the shortest suffix matching the "pattern".
  • %%pattern disables the longest suffix matching the "pattern".

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

Here we trim the shortest suffix matching the pattern -* , so ${foo%-*} will provide you with what you want.

Of course, there are many ways to do this using awk or sed , possibly reusing the sed command that you are already using. However, variable manipulation can be performed initially in bash without starting another process.

+8
source share

You can change the line 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--- 
+2
source share

I think you should use sed , at least after tr :

 var=$(curl https://avc.com/actuator/info | tr '"' '\n' | sed -n '/-/{s/-[^-]*$//;p;q}') 

-n means do not print by default. /-/ searches for a string containing a dash; Then it does s/-[^-]*$// to remove the last dash and everything after it, and then p to print and q to exit (so it only prints the first such line).


I assume that the output from curl essentially contains several lines, some of them with unwanted double quotes in them, and that you only need to match the first line containing the dash in general (which may not be the first line very well). After you have removed input to a single interesting line, you can use pure shell methods to get the desired result, but getting a single interesting line is not as trivial as some of the answers suggest.

+2
source share

All Articles