sed question.

Discussion in 'Mac Programming' started by Big Dave, Aug 23, 2010.

  1. Big Dave macrumors 6502

    Joined:
    Nov 27, 2007
    Location:
    Crestview, Fl
    #1
    I'm having some difficulty with sed syntax.
    I am reading in three numbers with spaces to the string coordinates. I don't think sed can handle the spaces. For example,
    if $coordiantes = 0.00 0.00 0.00
    and I do the following command:
    Code:
    sed -ie 's/coordinate_location/'$coordinates'/g' file
    I get the following error:
    sed: 1: "s/coordinate_location/0.00": unterminated substitute in regular expression

    What is the proper way to make a substitution with a string that contains spaces?
     
  2. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #2
    Wirelessly posted (Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0_1 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A306 Safari/6531.22.7)

    Try escaping the spaces with backslashes.

    B
     
  3. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #3
    Code:
    sed -e "s/coordinate_location/$coordinates/g"
    Did it for me. I tested it on the command line with cat so I omitted the -i flag in the example.
     
  4. Big Dave thread starter macrumors 6502

    Joined:
    Nov 27, 2007
    Location:
    Crestview, Fl
    #4
    I don't know how I would do that since the value of $coordinates is being read in by an awk command.

    Code:
    coordinates=`awk 'NR=='$i'' readin_file`
     
  5. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #5
    Actually, your problem has nothing at all to do with sed. You're simply passing a malformed argument to sed because of faulty shell quoting.

    Assuming that your statement:
    actually means:
    I have assigned the shell variable named coordinates the value "0.00 0.00 0.00", like so:
    Code:
    coordinates="0.00 0.00 0.00"
    

    At this point, the expression $coordinates or "$coordinates" will expand to the variable's value. The expression '$coordinates' will not, because $-expansion is suppressed inside single quotes.

    Now look at the command-line you posted:
    Code:
    sed -ie 's/coordinate_location/'$coordinates'/g' file
    
    If we do the expansion manually (always a useful exercise for understanding), we get this:
    Code:
    sed -ie 's/coordinate_location/'0.00 0.00 0.00'/g' file
    Now, knowing that the shell breaks command lines at whitespace, exactly how will this be turned into parameters? Like this:
    Code:
    sed
    -ie
    s/coordinate_location/0.00
    0.00 
    0.00/g 
    file
    From this, it's trivial to see that the s/pat/replace/ is malformed, because it lacks the third /.


    Here's a useful tip:
    Write a simple program that just outputs its argv values, one per line.
    Run this program to see what args are actually being passed in.

    For example, if the program were called 'argyle', then this command-line:
    Code:
    argyle -ie 's/coordinate_location/'$coordinates'/g' file
    
    would show output very like the breakdown given above.


    BTW, awk can do substitution, too. sed may not even be needed here.
     
  6. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #6
    Are you referring to adding escape characters to the string or something else?

    Did you try what I did? I created a file with the coordinate_location string in a few places mixed with random words, saved it and did:

    Code:
    cat test | sed -e "s/coordinate_location/$coordinates/g"
    And got this on stdout:

    Code:
    test test test test 0.00 0.00 0.00 test test 0.00 0.00 0.00 test
     
  7. Big Dave thread starter macrumors 6502

    Joined:
    Nov 27, 2007
    Location:
    Crestview, Fl
    #7
    I got it working by changing the single quotes to double quotes and removing the single quotes from $coordinates.

    Code:
    sed -ie "s/coordinate_location/$coordinates/g" file
    I'm the worst with syntax.
     
  8. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #8
    The rule of thumb I use is:
    double-quotes permit $ expansion; single-quotes don't.

    It's more complicated than that, but that's my rule of thumb.

    For example, this earlier command:
    Code:
    coordinates=`awk 'NR=='$i'' readin_file`
    
    could be expressed equally well as:
    Code:
    coordinates=`awk "NR==$i" readin_file`
    
    The other rule of thumb is that quoted strings can simply be concatenated. So if there's something that needs a mix of double-quotes (to get $ expansion) and single-quotes (to prevent it), I can usually just string things together without having to refer to the bash man page. For example, to echo the double-quoted string "don't $TERM", this would work:
    Code:
    echo '"'don"'t "'$TERM"'
    There are other ways of doing it, too, that may require referring to the man page. Example:
    Code:
    echo "\"don't \$TERM\""
    My rule of thumb there is that \ escapes within double-quotes, but not within qingle-quotes.

    Again, this illustrates the value of a command that simply prints its args, one per line. You can try out all kinds of things in order to get the quoting and escaping right, then paste it into where it's needed.
     

Share This Page