0

I am attempting to use the grep inside find/replace in a text edit program to separate numbers out from a single line.  So I wouldn't be using a prompt, just the find/replace function inside said program.  I've been able to use it to pull out pretty much everything I have needed from various documents, but this is somehow stumping me.  An example line would be something like:

Typ:01 Seq:0002 Spl:03

I want a single line code that can pull out the first number set, the second or the third.  Results would leave behind:

01

or

0002

or

03

I would like to be able to change the grep easily based on need to pull out any of the three numbers and remove everything else in the string.  I was thinking I could take one command and alter it as needed for the other two numbers, but ultimately it is three lines of code.

6
  • 1
    what does "or" mean in your example? I mean, these things are deterministic. What is it that you want to get? Commented Aug 1 at 19:54
  • I want a single line code that can pull out the first number set, the second or the third but not all at the same time. I hope that helps. I can run 3 commands, one for each number set.
    – Matt W
    Commented Aug 1 at 19:55
  • ah, so you want three lines of code? Commented Aug 1 at 19:55
  • Yes, I guess I was thinking I could take one line and alter it as needed for the other two numbers but ultimately it is 3 lines of code.
    – Matt W
    Commented Aug 1 at 19:56
  • 2
    What editor are you using? and why use an editor when you can do this very easily with a single Linux command?
    – userene
    Commented Aug 2 at 6:58

5 Answers 5

0

I assume that you’re using “grep” as a jargon word to refer to regular expression matching in general, and not to refer specifically to the grep program.  If I’m wrong, please clarify your question.

  • First:
    s/Typ:\([0123456789]*\) Seq:.* Spl:.*/\1/
    
  • Second:
    s/Typ:.* Seq:\([0123456789]*\) Spl:.*/\1/
    
  • Third:
    s/Typ:.* Seq:.* Spl:\([0123456789]*\)/\1/
    

Or

  • s/Typ:\([0123456789]*\) Seq:\([0123456789]*\) Spl:\([0123456789]*\)/\1/
    s/Typ:\([0123456789]*\) Seq:\([0123456789]*\) Spl:\([0123456789]*\)/\2/
    s/Typ:\([0123456789]*\) Seq:\([0123456789]*\) Spl:\([0123456789]*\)/\3/
    
0

In vi and with GNU grep, you can do:

!!grep -Po '\d+'

To extract all the sequences of digits in the current line on separate lines (replacing the original line). You can pipe to sed '2!d' for instance to pick the second only.

Without resorting to external commands, in vim, you can do:

:s/\d\+/\r&\r/2

To surround the 2nd sequence of digits with newline (yes, confusingly newline in there is represented with \r which usually represents carriage return) so it be on its own line in the middle.

Then you can delete the rest with ddkdd.

0

Is this what you want?

... assuming your data is separated by single one space ...

$ cat Example.txt
Typ:01 Seq:0002 Spl:03

$ tr " " "\n" < Example.txt
Typ:01
Seq:0002
Spl:03

and, split with : :

$ tr " " "\n" < Example.txt | cut -f2 -d:
01
0002
03

or maybe :

$ tr " " "\n" < Example.txt | cut -f1 -d:
Typ
Seq
Spl

2nd

$ tr " " "\n" < Example.txt | cut -f2 -d: | head -2 | tail -1
0002

0

Just an idea. I wrote this c-code for your example:

#include <stdio.h>

int main()
{

        int i = 0, k = 0;
        int newline = 0;

        char input_str[] = "Typ:01 Seq:0002 Spl:03";
        char output_str[1000] = ""; //max is here 1000 characters lengt

        while(input_str[i])
        {
                if(input_str[i] <= 57 && input_str[i] >= 48) //ASCII-Code of number-character checking
                {
                        output_str[k] = input_str[i]; //writes the digit into output_string
                        k++;
                        newline = 1;
                }
                else
                if(newline)
                {
                        output_str[k] = 10; //sets newline after a number has finished
                        k++;
                        newline = 0;
                }

        i++;
        }
        printf("%s\n",output_str);


        return 0;

}

It works with ASCII-Code numbers of characters. But this program doesn't work directly with your situation without modifying. I thought, maybe this idea could help you, if you understand c-code. Do you need something else?

0

Code examples below are written in either Perl or Raku. In both languages the input is first split on whitespace, and square-bracket indexing is used to pull out a particular text element (e.g. @a[0] or @a[1] or @a[2]). Finally \d digits are extracted out, g globally per text element:


Using Perl

~$ printf 'Typ:01 Seq:0002 Spl:03' | perl -ne 'my @a = split(" ", $_); for (@a[0]) {print m/\d+/g; print "\n" };'
01
~$ printf 'Typ:01 Seq:0002 Spl:03' | perl -ne 'my @a = split(" ", $_); for (@a[1]) {print m/\d+/g; print "\n" };'
0002
~$ printf 'Typ:01 Seq:0002 Spl:03' | perl -ne 'my @a = split(" ", $_); for (@a[2]) {print m/\d+/g; print "\n" };'
03

Using Raku (formerly known as Perl_6)

~$ printf 'Typ:01 Seq:0002 Spl:03' | raku -ne 'my @a = $_.split(" "); for @a[0] {put  m:g/\d+/ };'
01
~$ printf 'Typ:01 Seq:0002 Spl:03' | raku -ne 'my @a = $_.split(" "); for @a[1] {put  m:g/\d+/ };'
0002
~$ printf 'Typ:01 Seq:0002 Spl:03' | raku -ne 'my @a = $_.split(" "); for @a[2] {put  m:g/\d+/ };'
03

NOTE: Raku has a words routine which splits on whitespace for you. This lets you pick out your desired element by square-bracket indexing, e.g. .words[0] or .words[1] or .words[2]. So each Raku line above simplifies to:

~$ printf 'Typ:01 Seq:0002 Spl:03' | raku -ne 'put m:g/\d+/ for $_.words[0];'
01
~$ printf 'Typ:01 Seq:0002 Spl:03' | raku -ne 'put m:g/\d+/ for $_.words[1];'
0002
~$ printf 'Typ:01 Seq:0002 Spl:03' | raku -ne 'put m:g/\d+/ for $_.words[2];'
03

Perl References:
https://perldoc.perl.org
https://www.perl.org

Raku References:
https://docs.raku.org
https://raku.org

You must log in to answer this question.

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