1

I have the string like this feature/test-111-test-test. I need to extract string till the second dash and change forward slash to dash as well.

I have to do it in Makefile using shell syntax and there for me doesn't work some regular expression which can help or this case

Finally I have to get smth like this:
input - feature/test-111-test-test
output - feature-test-111- or at least feature-test-111

feature/test-111-test-test | grep -oP '\A(?:[^-]++-??){2}' | sed -e 's/\//-/g')

But grep -oP doesn't work in my case. This regexp doesn't work as well - (.*?-.*?)-.*.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    *"`grep -oP doesn't work`"*. Are you sure it was just `grep` that didn't work. The command you posted seems broken, the first part is just a string. I would have expected something like `echo` to print that string. Also, at the end there is a stray `)`. – Socowi Apr 24 '21 at 20:30

7 Answers7

2

Another sed solution using a capture group and regex/pattern iteration (same thing Socowi used):

$ s='feature/test-111-test-test'
$ sed -E 's/\//-/;s/^(([^-]*-){3}).*$/\1/' <<< "${s}"
feature-test-111-

Where:

  • -E - enable extended regex support
  • s/\//-/ - replace / with -
  • s/^....*$/ - match start and end of input line
  • (([^-]-){3}) - capture group #1 that consists of 3 sets of anything not - followed by -
  • \1 - print just the capture group #1 (this will discard everything else on the line that's not part of the capture group)

To store the result in a variable:

$ url=$(sed -E 's/\//-/;s/^(([^-]*-){3}).*$/\1/' <<< "${s}")
$ echo $url
feature-test-111-
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
1

You can use awk keeping in mind that in Makefile the $ char in awk command must be doubled:

url=$(shell echo 'feature/test-111-test-test' | awk -F'-' '{gsub(/\//, "-", $$1);print $$1"-"$$2"-"}')
echo "$url"
# => feature-test-111-

See the online demo. Here, -F'-' sets the field delimiter as -, gsub(/\//, "-", $1) replaces / with - in Field 1 and print $1"-"$2"-" prints the value of --separated Field 1 and 2.

Or, with a regex as a field delimiter:

url=$(shell echo 'feature/test-111-test-test' | awk -F'[-/]' '{print $$1"-"$$2"-"$$3"-"}')
echo "$url"
# => feature-test-111-

The -F'[-/]' option sets the field separator to - and /.

The '{print $1"-"$2"-"$3"-"}' part prints the first, second and third value with a separating hyphen.

See the online demo.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • Thanks for reply @wiktor-stribiżew. For me it doesn't work properly. s='feature/test-111-test-test' url=$(shell awk -F'[-/]' '{print $1"-"$2"-"$3"-"}' <<< "$s"). I'm getting just 3 hyphens s='feature/test-111-test-test' url=--- – Vitalii Sotnichenko Apr 24 '21 at 20:38
  • 1
    @VitaliiSotnichenko In Makefile, `$` [is special](https://stackoverflow.com/a/30445374/3832970). You need to double it, so use `url=$(shell awk -F'[-/]' '{print $$1"-"$$2"-"$$3"-"}' <<< "$s")` – Wiktor Stribiżew Apr 24 '21 at 21:02
  • @VitaliiSotnichenko Do my updated solutions work now? – Wiktor Stribiżew Apr 24 '21 at 21:05
  • Yes, it's working now. Do you know by any chance how to add prefix to the beginning of line. I'd like to add http:// but since I have replacement / to -, http:// changes to http:--. I have this line so far - echo http://$(s) | awk -F'-' '{gsub(/\//, "-", $$1);print $$1"-"$$2"-"}' – Vitalii Sotnichenko Apr 24 '21 at 21:17
  • 1
    @VitaliiSotnichenko You can append `http://` in the `print` command, `awk -F'-' '{gsub(/\//, "-", $$1);print "http://"$$1"-"$$2"-"}'` or `awk -F'[-/]' '{print "http://"$$1"-"$$2"-"$$3"-"}'` – Wiktor Stribiżew Apr 24 '21 at 21:23
  • 1
    works perfectly for me, thank you so much – Vitalii Sotnichenko Apr 24 '21 at 21:37
1

To get the nth occurrence of a character C you don't need fancy perl regexes. Instead, build a regex of the form "(anything that isn't C, then C) for n times":

grep -Eo '([^-]*-){2}' | tr / - 
Socowi
  • 25,550
  • 3
  • 32
  • 54
1

With sed and cut

echo feature/test-111-test-test| cut -d'-' -f-2 |sed 's/\//-/'

Output

feature-test-111

echo feature/test-111-test-test| cut -d'-' -f-2 |sed 's/\//-/;s/$/-/'

Output

feature-test-111-
Jetchisel
  • 7,493
  • 2
  • 19
  • 18
0

You can use the simple BRE regex form of not something then that something which is [^-]*- to get all characters other than - up to a -.

This works:

echo 'feature/test-111-test-test' | sed -nE 's/^([^/]*)\/([^-]*-[^-]*-).*/\1-\2/p'
feature-test-111-
dawg
  • 98,345
  • 23
  • 131
  • 206
0

Another idea using parameter expansions/substitutions:

s='feature/test-111-test-test'
tail="${s//\//-}"                   # replace '/' with '-'

# split first field from rest of fields ('-' delimited); do this 3x times

head="${tail%%-*}"                  # pull first field
tail="${tail#*-}"                   # drop first field

head="${head}-${tail%%-*}"          # pull first field; append to previous field
tail="${tail#*-}"                   # drop first field

head="${head}-${tail%%-*}-"         # pull first field; append to previous fields; add trailing '-'

$ echo "${head}"
feature-test-111-
markp-fuso
  • 28,790
  • 4
  • 16
  • 36
0

A short sed solution, without extended regular expressions:

sed 's|\(.*\)/\([^-]*-[^-]*\).*|\1-\2|'
Beta
  • 96,650
  • 16
  • 149
  • 150