Find the answer to your Linux question:
Results 1 to 9 of 9
Hi linux user, I try to make an easy string substitution inside a bash script. I need to substitute the substring "=>" and all the space round this with one ...
  1. #1
    Just Joined!
    Join Date
    Jul 2007
    Posts
    4

    Unhappy bash string substitution problem

    Hi linux user,
    I try to make an easy string substitution inside a bash script.
    I need to substitute the substring "=>" and all the space round this with
    one symbol ... example:

    original string: "xyz => uvw"
    substitution : "xyz,uvw"

    I have substituted " => " with this symbol ","

    If I try to do this using a regular expression in a bash script:

    ------------test.sh------------
    #!/bin/bash
    st="xyz => uvw"
    echo ${st/[ ]*=>[ ]*/,}
    ------------------------------

    I obtain in output this:
    xyz,

    How can I obtain che correct result? :
    xyz,uvw

    can you help me?
    p.s. I don't want to use external tool like sed or perl for performance reason.

  2. #2
    Linux User
    Join Date
    Aug 2006
    Posts
    458
    Code:
     echo ${st/ => /,}

  3. #3
    Linux User
    Join Date
    Jun 2007
    Posts
    318
    The form you're using (/) replaces only the 1st occurance. Use the 2nd form (//) which replaces all occurances. Plus, to handle TABs as well as spaces this is the command:

    echo "${st//[[:space:]]*=>[[:space:]]*/,}"

  4. #4
    Just Joined!
    Join Date
    Jul 2007
    Posts
    4
    Hi vsemaska,
    thank you for your reply, but if you apply your example with my example you obtain this:

    xyz,

    your script miss the second part of the string "uvw"
    have you test your script?
    I use a bash with this version "version 3.1.17(1)-release".

  5. #5
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    The problem is that the ${s/foo/bar} syntax actually uses shell patterns, I believe, and not regular expressions.

    If we look at /[[:space:]]*=>[[:space:]]*/ as a shell pattern, it says "A space character, followed by any number of characters, followed by '=>', followed by a space character, followed by any number of characters". And sure enough, this _does_ match " => uvw". Remember that in shell patterns, '*' means 0 more characters, and '?' means exactly one character.

    Bash 3.0 supports regular expression matching, but I don't believe that it supports regular expression substitution. To do what you want would require sed.

    However, I just checked the bash man page (under 'Pattern Matching'), and learned about composite patterns. These require that extglob be set (use the 'shopt' command to work with these), but they would provide something like:
    Code:
    ${st/*([[:space:]])=>*([[:space:]])/,}
    DISTRO=Arch
    Registered Linux User #388732

  6. #6
    Just Joined!
    Join Date
    Jul 2007
    Posts
    4
    EUREKA!!!
    I found the solution
    I don't know why it works but It works:

    ------------test2.sh------------------------
    #!/bin/bash
    st="xyz => uvw"
    echo "${st//[[:space:]]*=>*[[:space:]]/,}"
    -------------------------------------------

    I have the output I want:

    --------- output ------------
    $ ./test2.sh
    xyz,uvw
    -----------------------------

    thank you Cabhan for your help, I hope the solution I found can help you
    in the future.

    bye Andrea.

  7. #7
    Just Joined!
    Join Date
    Jul 2007
    Posts
    4
    Hi script bash user ...
    please look my previous post ... this is an half success because
    my previous script it works only .. if are present spaces " " around the
    "=>" substring.

    ------------test2.sh------------------------
    #!/bin/bash
    st1="xyz => uvw"
    st2="xyz=> uvw"
    echo "${st1//[[:space:]]*=>*[[:space:]]/,}"
    echo "${st2//[[:space:]]*=>*[[:space:]]/,}"
    -------------------------------------------

    --------- output ------------
    $ ./test2.sh
    xyz,uvw
    xyz=> uvw
    -----------------------------

    My previous script it works only for st1 and not for st2

  8. #8
    Trusted Penguin Cabhan's Avatar
    Join Date
    Jan 2005
    Location
    Seattle, WA, USA
    Posts
    3,230
    Yes. As I said in my last post, '*' here does not mean '0 more more of the preceding', but rather represents characters in its own right. Which means that [[:space:]] is standing for one space character.

    To get around this, you need to somehow apply a quantifier to the [[:space:]]. You can do this either by setting extglob with shopt and using *(...) (as I explained in my last post), or using an external tool like sed.


    Also, for the record, precisely because this is a shell pattern, your current '*'s do not help. For instance, your current pattern: /[[:space:]]*=>*[[:space:]]/ will match ' a=>hello '. Which you obviously don't want it to.
    DISTRO=Arch
    Registered Linux User #388732

  9. #9
    Linux Enthusiast
    Join Date
    Aug 2006
    Posts
    631
    As mentioned by Cabhan sed is the tool for this job, to replace spaces or/and tabs by a comma you can try this:

    Code:
    echo "$st"|sed 's/[[:blank:]]*=>[[:blank:]]*/,/'
    The asterix behind the classes matches for zero or more tabs or spaces.

    Regards

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...