0

I have a string structure like this bob-type-8.2-mp2-2017-93-43-11-65-48.spr form where I just need to extract 8.2-mp2-2017-93-43-11-65-48 .

It means the output string should contain all the characters after encountering the first numerical value and then removing the .spr from that.

How can I do that?

7 Answers 7

1

Try this:

echo "bob-type-8.2-mp2-2017-93-43-11-65-48.spr" | sed 's/^[^0-9]*//;s/\.[^.]*$//'

Output will:

8.2-mp2-2017-93-43-11-65-48

Explanation:

Sed uses pattern 's/pattern/replace_pattern/' to find pattern and replace it to replace_pattern

So, pattern 's/^[^0-9]*//' get all symbols from start of line and before first digits occurance and replace it to nothing (replace_pattern are empty).

The next step - delete extention. We can do this with the same sed's pattern 's///'.

s/\.[^.]*$// - find all symbols that not a . at the end $ of line and replace it to nothing.

; - devide patterns.

For best understanding you could use this command instead:

echo "bob-type-8.2-mp2-2017-93-43-11-65-48.spr" | sed -e 's/^[^0-9]*//' -e 's/\.[^.]*$//'
1
  • Note that it assumes the file name doesn't contain newline characters (or bytes not forming valid characters, or backslash characters depending on the echo implementation) Oct 3, 2017 at 16:33
1

In Bash, with extglob:

$ shopt -s extglob
$ var=bob-type-8.2-mp2-2017-93-43-11-65-48.spr
$ res=${var##*([^0-9])}
$ res=${res%.spr}
$ echo "$res"
8.2-mp2-2017-93-43-11-65-48

*([^0-9]) matches any string of non-digits, ${var##pattern} removes the longest matching pattern from the beginning of the string, ${var%pattern} removes the (shortest) matching pattern from the end.

1

another approach with sed.

sed 's/^[^[[:digit:]]*\(.*\)\.spr$/\1/' <<<"bob-type-8.2-mp2-2017-93-43-11-65-48.spr"
  • ^[^[[:digit:]]* match everything start from beginning of the string until first digit seen; Same as ^[^0-9]*

  • \(.*\) matches everything after above matches and parentheses \(...\) are used to capture a group match with \1 as its back-reference.

  • \.spr$ matches a literal point followed by spr at the end of input string.

  • \1 prints only captured group match.

1

So many sed answers! How about a pure bash solution using =~ pattern matching and the not-so-common back-reference array BASH_REMATCH?

# put your string in variable named 'input'
patt='^[^0-9]*(.*)\..*' && [[ $input =~ $patt ]] && echo "${BASH_REMATCH[1]}"

Just to stand apart from the crowd. ;)

1

POSIXly:

string=bob-type-8.2-mp2-2017-93-43-11-65-48.spr
newstring=${string#"${string%%[0-9]*}"}
newstring=${newstring%.*}
  • ${string#pattern}: remove from the start of $string what is matched by pattern which in this case is:
  • ${string%%[0-9]*} $string stripped of its longest trailing part that matches the [0-9]* pattern. So that's the part up to the first digit.
  • ${newstring%.*}: $string stripped of its shortest trailing part that matches the .* pattern. So removes the extension.

With zsh:

newstring=${(M)${string:r}%%[0-9]*}
  • ${string:r}: expands to the root name (removed the extension) like in csh
  • ${(M)var%%pattern}, return what is Matched by the %% operator (which without (M) would remove the longest part at the end that would match the pattern like in POSIX shells).
1

How about this?

echo bob-type-8.2-mp2-2017-93-43-11-65-48.spr | sed -r 's/^[^0-9]*(.*)\..*$/\1/'

This takes everything from the first numerical value encountered after the beginning of the string to the end of the string minus the last dot and what follows it.

  • ^[^0-9]* skips all non-numerical: NOT zero to nine ([^0-9]), 0 to N times (*), from the beginning of the line (^).
  • \..*$ matches any character (.), 0 to N times (*), before the end of the line ($), and preceeded by a dot (\.). In our case this is .spr but it could apply to any other "dot + N-characters" file extension: .s, .yaythatsacoolextension, etc, work as well.
  • (.*), referred as \1 later, keeps (this is the purpose of the parenthesis, we couldn't refer to it later otherwise) what's in the middle: any character (.), 0 to N times (*). This gives us 8.2-mp2-2017-93-43-11-65-48.

So if you need to list into a file the normalized names of all .spr contained in the current directory, for example, you can do something like this:

for i in *.spr
do
    echo $i | sed -r 's/^[^0-9]*(.*)\..*$/\1/' >> mylist.lst
done

And tomorrow, should you need to do that with .blop files instead, just turn the *.sprabove into *.blop.

0
0

Sed is one of the possible approaches

echo bob-type-8.2-mp2-2017-93-43-11-65-48.spr | sed 's/^[^0-9]*//;s/....$//'
8.2-mp2-2017-93-43-11-65-48

regexps mean

  1. replace all non-numerical symbols from beginning with nothing till the first numerical
  2. replace last 4 chars with nothinig
1
  • yep, overseen that, updated now
    – Tagwint
    Oct 3, 2017 at 13:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.