Extract substring according to regexp with sed or grep












4















In a (BSD) UNIX environment, I would like to capture a specific substring using a regular expression.



Assume that the dmesg command output would include the following line:



pass2: <Marvell Console 1.01> Removable Processor SCSI device


I would like to capture the text between the < and > characters, like



dmesg | <sed command>



should output:



Marvell Console 1.01


However, it should not output anything if the regex does not match. Many solutions including sed -e 's/$regex/1/ will output the whole input if no match is found, which is not what i want.



The corresponding regexp could be:
regex="^pass2: <(.*)>"



How would i properly do a regex match using sed or grep? Note that the grep -P option is unavailable in my BSD UNIX distribution. The sed -E option is available, however.










share|improve this question























  • It's possibly better to parse the output of camcontrol devlist than the output of dmesg.

    – JdeBP
    yesterday
















4















In a (BSD) UNIX environment, I would like to capture a specific substring using a regular expression.



Assume that the dmesg command output would include the following line:



pass2: <Marvell Console 1.01> Removable Processor SCSI device


I would like to capture the text between the < and > characters, like



dmesg | <sed command>



should output:



Marvell Console 1.01


However, it should not output anything if the regex does not match. Many solutions including sed -e 's/$regex/1/ will output the whole input if no match is found, which is not what i want.



The corresponding regexp could be:
regex="^pass2: <(.*)>"



How would i properly do a regex match using sed or grep? Note that the grep -P option is unavailable in my BSD UNIX distribution. The sed -E option is available, however.










share|improve this question























  • It's possibly better to parse the output of camcontrol devlist than the output of dmesg.

    – JdeBP
    yesterday














4












4








4








In a (BSD) UNIX environment, I would like to capture a specific substring using a regular expression.



Assume that the dmesg command output would include the following line:



pass2: <Marvell Console 1.01> Removable Processor SCSI device


I would like to capture the text between the < and > characters, like



dmesg | <sed command>



should output:



Marvell Console 1.01


However, it should not output anything if the regex does not match. Many solutions including sed -e 's/$regex/1/ will output the whole input if no match is found, which is not what i want.



The corresponding regexp could be:
regex="^pass2: <(.*)>"



How would i properly do a regex match using sed or grep? Note that the grep -P option is unavailable in my BSD UNIX distribution. The sed -E option is available, however.










share|improve this question














In a (BSD) UNIX environment, I would like to capture a specific substring using a regular expression.



Assume that the dmesg command output would include the following line:



pass2: <Marvell Console 1.01> Removable Processor SCSI device


I would like to capture the text between the < and > characters, like



dmesg | <sed command>



should output:



Marvell Console 1.01


However, it should not output anything if the regex does not match. Many solutions including sed -e 's/$regex/1/ will output the whole input if no match is found, which is not what i want.



The corresponding regexp could be:
regex="^pass2: <(.*)>"



How would i properly do a regex match using sed or grep? Note that the grep -P option is unavailable in my BSD UNIX distribution. The sed -E option is available, however.







sed grep regular-expression






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked yesterday









SteinerSteiner

788




788













  • It's possibly better to parse the output of camcontrol devlist than the output of dmesg.

    – JdeBP
    yesterday



















  • It's possibly better to parse the output of camcontrol devlist than the output of dmesg.

    – JdeBP
    yesterday

















It's possibly better to parse the output of camcontrol devlist than the output of dmesg.

– JdeBP
yesterday





It's possibly better to parse the output of camcontrol devlist than the output of dmesg.

– JdeBP
yesterday










3 Answers
3






active

oldest

votes


















7














Try this,



sed -nE 's/^pass2:.*<(.*)>.*$/1/p'


Or POSIXly (-E has not made it to the POSIX standard yet as of 2019):



sed -n 's/^pass2:.*<(.*)>.*$/1/p'


Output:



$ printf '%sn' 'pass2: <Marvell Console 1.01> Removable Processor SCSI device' | sed -nE 's/^pass2:.*<(.*)>.*$/1/p'
Marvell Console 1.01


This will only print the last occurrence of <...> for each line.






share|improve this answer


























  • This works for me, with both the -n parameter and the /p suffix inside the regex. Full command i used: dmesg | sed -nE 's/^pass2: <(.*)>.*$/1/p

    – Steiner
    yesterday






  • 1





    Why not use <([^>]+)>? I.e. not-> one-or-more times

    – Rich
    yesterday






  • 1





    sed regex is per default non-greedy, so it's not necessary here. But it would work, too.

    – RoVo
    13 hours ago



















5














How about -o under grep to just print the matching part? We still need to remove the <>, though, but tr works there.



dmesg |egrep -o "<([a-zA-Z.0-9 ]+)>" |tr -d "<>"
Marvell Console 1.01





share|improve this answer

































    2














    I tried below 3 methods by using sed, awk and python



    sed command



    echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | sed "s/.*<//g"|sed "s/>.*//g"


    output



    Marvell Console 1.01


    awk command



    echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | awk -F "[<>]" '{print $2}'


    output



    Marvell Console 1.01


    python



    #!/usr/bin/python
    import re
    h=
    k=open('l.txt','r')
    l=k.readlines()
    for i in l:
    o=i.split(' ')
    for i in o[1:4]:
    h.append(i)
    print (" ".join(h)).replace('>','').replace('<','')


    output



    Marvell Console 1.01





    share|improve this answer


























    • I was thinking the awk approach too. Should you constrain your print to lines beginning with "pass2:"? The OP didn't provide sufficient detail, but I can imagine that a naive pattern match would not be quite what was wanted.

      – jwm
      20 hours ago











    • Python can read from standard in, though perl specializes in this kind of text processing if you’re moving into higher level scripting languages.

      – D. Ben Knoble
      16 hours ago











    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f507188%2fextract-substring-according-to-regexp-with-sed-or-grep%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    7














    Try this,



    sed -nE 's/^pass2:.*<(.*)>.*$/1/p'


    Or POSIXly (-E has not made it to the POSIX standard yet as of 2019):



    sed -n 's/^pass2:.*<(.*)>.*$/1/p'


    Output:



    $ printf '%sn' 'pass2: <Marvell Console 1.01> Removable Processor SCSI device' | sed -nE 's/^pass2:.*<(.*)>.*$/1/p'
    Marvell Console 1.01


    This will only print the last occurrence of <...> for each line.






    share|improve this answer


























    • This works for me, with both the -n parameter and the /p suffix inside the regex. Full command i used: dmesg | sed -nE 's/^pass2: <(.*)>.*$/1/p

      – Steiner
      yesterday






    • 1





      Why not use <([^>]+)>? I.e. not-> one-or-more times

      – Rich
      yesterday






    • 1





      sed regex is per default non-greedy, so it's not necessary here. But it would work, too.

      – RoVo
      13 hours ago
















    7














    Try this,



    sed -nE 's/^pass2:.*<(.*)>.*$/1/p'


    Or POSIXly (-E has not made it to the POSIX standard yet as of 2019):



    sed -n 's/^pass2:.*<(.*)>.*$/1/p'


    Output:



    $ printf '%sn' 'pass2: <Marvell Console 1.01> Removable Processor SCSI device' | sed -nE 's/^pass2:.*<(.*)>.*$/1/p'
    Marvell Console 1.01


    This will only print the last occurrence of <...> for each line.






    share|improve this answer


























    • This works for me, with both the -n parameter and the /p suffix inside the regex. Full command i used: dmesg | sed -nE 's/^pass2: <(.*)>.*$/1/p

      – Steiner
      yesterday






    • 1





      Why not use <([^>]+)>? I.e. not-> one-or-more times

      – Rich
      yesterday






    • 1





      sed regex is per default non-greedy, so it's not necessary here. But it would work, too.

      – RoVo
      13 hours ago














    7












    7








    7







    Try this,



    sed -nE 's/^pass2:.*<(.*)>.*$/1/p'


    Or POSIXly (-E has not made it to the POSIX standard yet as of 2019):



    sed -n 's/^pass2:.*<(.*)>.*$/1/p'


    Output:



    $ printf '%sn' 'pass2: <Marvell Console 1.01> Removable Processor SCSI device' | sed -nE 's/^pass2:.*<(.*)>.*$/1/p'
    Marvell Console 1.01


    This will only print the last occurrence of <...> for each line.






    share|improve this answer















    Try this,



    sed -nE 's/^pass2:.*<(.*)>.*$/1/p'


    Or POSIXly (-E has not made it to the POSIX standard yet as of 2019):



    sed -n 's/^pass2:.*<(.*)>.*$/1/p'


    Output:



    $ printf '%sn' 'pass2: <Marvell Console 1.01> Removable Processor SCSI device' | sed -nE 's/^pass2:.*<(.*)>.*$/1/p'
    Marvell Console 1.01


    This will only print the last occurrence of <...> for each line.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited yesterday









    Stéphane Chazelas

    310k57586945




    310k57586945










    answered yesterday









    RoVoRoVo

    3,332317




    3,332317













    • This works for me, with both the -n parameter and the /p suffix inside the regex. Full command i used: dmesg | sed -nE 's/^pass2: <(.*)>.*$/1/p

      – Steiner
      yesterday






    • 1





      Why not use <([^>]+)>? I.e. not-> one-or-more times

      – Rich
      yesterday






    • 1





      sed regex is per default non-greedy, so it's not necessary here. But it would work, too.

      – RoVo
      13 hours ago



















    • This works for me, with both the -n parameter and the /p suffix inside the regex. Full command i used: dmesg | sed -nE 's/^pass2: <(.*)>.*$/1/p

      – Steiner
      yesterday






    • 1





      Why not use <([^>]+)>? I.e. not-> one-or-more times

      – Rich
      yesterday






    • 1





      sed regex is per default non-greedy, so it's not necessary here. But it would work, too.

      – RoVo
      13 hours ago

















    This works for me, with both the -n parameter and the /p suffix inside the regex. Full command i used: dmesg | sed -nE 's/^pass2: <(.*)>.*$/1/p

    – Steiner
    yesterday





    This works for me, with both the -n parameter and the /p suffix inside the regex. Full command i used: dmesg | sed -nE 's/^pass2: <(.*)>.*$/1/p

    – Steiner
    yesterday




    1




    1





    Why not use <([^>]+)>? I.e. not-> one-or-more times

    – Rich
    yesterday





    Why not use <([^>]+)>? I.e. not-> one-or-more times

    – Rich
    yesterday




    1




    1





    sed regex is per default non-greedy, so it's not necessary here. But it would work, too.

    – RoVo
    13 hours ago





    sed regex is per default non-greedy, so it's not necessary here. But it would work, too.

    – RoVo
    13 hours ago













    5














    How about -o under grep to just print the matching part? We still need to remove the <>, though, but tr works there.



    dmesg |egrep -o "<([a-zA-Z.0-9 ]+)>" |tr -d "<>"
    Marvell Console 1.01





    share|improve this answer






























      5














      How about -o under grep to just print the matching part? We still need to remove the <>, though, but tr works there.



      dmesg |egrep -o "<([a-zA-Z.0-9 ]+)>" |tr -d "<>"
      Marvell Console 1.01





      share|improve this answer




























        5












        5








        5







        How about -o under grep to just print the matching part? We still need to remove the <>, though, but tr works there.



        dmesg |egrep -o "<([a-zA-Z.0-9 ]+)>" |tr -d "<>"
        Marvell Console 1.01





        share|improve this answer















        How about -o under grep to just print the matching part? We still need to remove the <>, though, but tr works there.



        dmesg |egrep -o "<([a-zA-Z.0-9 ]+)>" |tr -d "<>"
        Marvell Console 1.01






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited yesterday









        ilkkachu

        61.9k10101178




        61.9k10101178










        answered yesterday









        Radek RadekRadek Radek

        1014




        1014























            2














            I tried below 3 methods by using sed, awk and python



            sed command



            echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | sed "s/.*<//g"|sed "s/>.*//g"


            output



            Marvell Console 1.01


            awk command



            echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | awk -F "[<>]" '{print $2}'


            output



            Marvell Console 1.01


            python



            #!/usr/bin/python
            import re
            h=
            k=open('l.txt','r')
            l=k.readlines()
            for i in l:
            o=i.split(' ')
            for i in o[1:4]:
            h.append(i)
            print (" ".join(h)).replace('>','').replace('<','')


            output



            Marvell Console 1.01





            share|improve this answer


























            • I was thinking the awk approach too. Should you constrain your print to lines beginning with "pass2:"? The OP didn't provide sufficient detail, but I can imagine that a naive pattern match would not be quite what was wanted.

              – jwm
              20 hours ago











            • Python can read from standard in, though perl specializes in this kind of text processing if you’re moving into higher level scripting languages.

              – D. Ben Knoble
              16 hours ago
















            2














            I tried below 3 methods by using sed, awk and python



            sed command



            echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | sed "s/.*<//g"|sed "s/>.*//g"


            output



            Marvell Console 1.01


            awk command



            echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | awk -F "[<>]" '{print $2}'


            output



            Marvell Console 1.01


            python



            #!/usr/bin/python
            import re
            h=
            k=open('l.txt','r')
            l=k.readlines()
            for i in l:
            o=i.split(' ')
            for i in o[1:4]:
            h.append(i)
            print (" ".join(h)).replace('>','').replace('<','')


            output



            Marvell Console 1.01





            share|improve this answer


























            • I was thinking the awk approach too. Should you constrain your print to lines beginning with "pass2:"? The OP didn't provide sufficient detail, but I can imagine that a naive pattern match would not be quite what was wanted.

              – jwm
              20 hours ago











            • Python can read from standard in, though perl specializes in this kind of text processing if you’re moving into higher level scripting languages.

              – D. Ben Knoble
              16 hours ago














            2












            2








            2







            I tried below 3 methods by using sed, awk and python



            sed command



            echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | sed "s/.*<//g"|sed "s/>.*//g"


            output



            Marvell Console 1.01


            awk command



            echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | awk -F "[<>]" '{print $2}'


            output



            Marvell Console 1.01


            python



            #!/usr/bin/python
            import re
            h=
            k=open('l.txt','r')
            l=k.readlines()
            for i in l:
            o=i.split(' ')
            for i in o[1:4]:
            h.append(i)
            print (" ".join(h)).replace('>','').replace('<','')


            output



            Marvell Console 1.01





            share|improve this answer















            I tried below 3 methods by using sed, awk and python



            sed command



            echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | sed "s/.*<//g"|sed "s/>.*//g"


            output



            Marvell Console 1.01


            awk command



            echo "pass2: <Marvell Console 1.01> Removable Processor SCSI device" | awk -F "[<>]" '{print $2}'


            output



            Marvell Console 1.01


            python



            #!/usr/bin/python
            import re
            h=
            k=open('l.txt','r')
            l=k.readlines()
            for i in l:
            o=i.split(' ')
            for i in o[1:4]:
            h.append(i)
            print (" ".join(h)).replace('>','').replace('<','')


            output



            Marvell Console 1.01






            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday









            ilkkachu

            61.9k10101178




            61.9k10101178










            answered yesterday









            Praveen Kumar BSPraveen Kumar BS

            1,6351311




            1,6351311













            • I was thinking the awk approach too. Should you constrain your print to lines beginning with "pass2:"? The OP didn't provide sufficient detail, but I can imagine that a naive pattern match would not be quite what was wanted.

              – jwm
              20 hours ago











            • Python can read from standard in, though perl specializes in this kind of text processing if you’re moving into higher level scripting languages.

              – D. Ben Knoble
              16 hours ago



















            • I was thinking the awk approach too. Should you constrain your print to lines beginning with "pass2:"? The OP didn't provide sufficient detail, but I can imagine that a naive pattern match would not be quite what was wanted.

              – jwm
              20 hours ago











            • Python can read from standard in, though perl specializes in this kind of text processing if you’re moving into higher level scripting languages.

              – D. Ben Knoble
              16 hours ago

















            I was thinking the awk approach too. Should you constrain your print to lines beginning with "pass2:"? The OP didn't provide sufficient detail, but I can imagine that a naive pattern match would not be quite what was wanted.

            – jwm
            20 hours ago





            I was thinking the awk approach too. Should you constrain your print to lines beginning with "pass2:"? The OP didn't provide sufficient detail, but I can imagine that a naive pattern match would not be quite what was wanted.

            – jwm
            20 hours ago













            Python can read from standard in, though perl specializes in this kind of text processing if you’re moving into higher level scripting languages.

            – D. Ben Knoble
            16 hours ago





            Python can read from standard in, though perl specializes in this kind of text processing if you’re moving into higher level scripting languages.

            – D. Ben Knoble
            16 hours ago


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f507188%2fextract-substring-according-to-regexp-with-sed-or-grep%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Category:香港粉麵

            List *all* the tuples!

            Channel [V]