Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie
Hi there,
There is an issue with role permissions that is being worked on at the moment.
If you are having trouble with access or permissions on regional forums please post here to get access: https://www.boards.ie/discussion/2058365403/you-do-not-have-permission-for-that#latest

sed error on OSX

  • 20-04-2012 5:05am
    #1
    Registered Users, Registered Users 2 Posts: 599 ✭✭✭


    I am looking to change a reference to a link on some (60+) Selenium test scripts, html files.

    I want to change 'link=Sign Out' to xpath '//a[contains(@href, '/user/logout')]'

    When I run the following sed command I get an error:

    sed -i '' 's/link=Sign Out/\/\/a[contains(@href, \'\/user\/logout\')]/g' *.html


    -bash: syntax error near unexpected token `)'

    Any ideas?


Comments

  • Registered Users, Registered Users 2 Posts: 1,931 ✭✭✭PrzemoF


    escape space? " " (space) -> "\ " (backslash - space)


  • Registered Users, Registered Users 2 Posts: 201 ✭✭jonathan11


    Could be wrong but I don't think the "-i" option is available on mac.


  • Registered Users, Registered Users 2 Posts: 453 ✭✭Ant


    jonathan11 wrote: »
    Could be wrong but I don't think the "-i" option is available on mac.

    It used to be a case that the -i option was a feature of GNU sed rather than the BSD version that comes with Mac OS X. I just found an online man page which shows that inplace editing is now a feature.

    I first thought that the error message my have been indicating that the opening and closing parentheses might have to be escaped. However, I think what's happening is that bash interprets the second single quote as closing that expression. I don't have access to a Mac right now but I'd try enclosing the whole substitution expression in double quotes like so:
    sed -i .bak "s/link=Sign Out/\/\/a[contains(@href, \'\/user\/logout\')]/g" *.htm
    

    You probably won't have to escape the single quotes if the whole expression is enclosed in double quotes.

    I'd also suggest that you provide an extension such as .bak to the -i option until you're happy the command works as you intend it to.


  • Registered Users, Registered Users 2 Posts: 2 24365confused


    I don't know if the OP has figured it out but for the record here's the results I found.

    Firstly:
    My advice would be that you should NEVER attempt to test out a sed command using the -i unless you want to destroy files needlessly. :eek:

    Rather, you should test ONE file to console, to see if it works.

    In other words MAKE IT SIMPLE, just to check out the syntax before actually running it.

    This is how I figured it out (and I would consider myself NOT an expert by any stretch, as you will see).

    Create a variable
    a='link=Sign Out'

    then

    echo $a | sed 's/link=Sign Out/\/\/a[contains(@href, \'\/user\/logout\')]/g'
    bash: syntax error near unexpected token `)'

    Then what I did was to take it 'word by word' (the one thing I did do was replace the syntax s/find/replace/ with

    sed 's:find:replace:'

    to clear out some of the numerous backslashes, though I put them back in the long run, after everything worked out.

    $ echo $a | sed 's:link=Sign Out:test:'
    test

    $ echo $a | sed 's:link=Sign Out:a[contains:'
    a[contains

    $ echo $a | sed 's:link=Sign Out:a[contains(@:'


    $ echo $a | sed 's:link=Sign Out:a[contains(@href:'
    a[contains(@href

    $ echo $a | sed 's:link=Sign Out:a[contains(@href]:'
    a[contains(@href]

    $ echo $a | sed 's:link=Sign Out:a[contains(@href,]:'
    a[contains(@href,]

    $ echo $a | sed 's:link=Sign Out:a[contains(@href, ]:'
    a[contains(@href, ]

    $ echo $a | sed 's:link=Sign Out:a[contains(@href, \']:'
    >

    so that is where the problem is the ==>> '

    \x27 is the hex code for the char '

    so

    $ echo $a | sed 's:link=Sign Out:a[contains(@href, \x27 ]:'
    a[contains(@href, ' ]

    soooooo

    putting back the backslashes etc

    $ echo $a | sed 's/link=Sign Out/\/\/a[contains(@href, \x27\/user\/logout\x27)]/g'
    //a[contains(@href, '/user/logout')] success!!

    I find that nearly always I am able to work it out for myself. All you have to do is take it piece by piece, slowly but surely, as I did. It is also a very interesting experience and a way to learn more. For some reason the ' with the backslash just doesn't work - perhaps it's a bug?

    Again - test it out but NOT using the -i yet. That should only be used when you are TOTALY sure everything works as expected.

    Hope that helps.

    Later I realised that this isn't a bug. The original error message actually gave the hint - bash. If you use ' then bash will see ALL the chars as literal chars until it find the closing ' - therefore it will never see the escape char \ as an escape char. Mea Culpa for daring to doubt bash OR sed. :)


  • Registered Users, Registered Users 2 Posts: 453 ✭✭Ant


    Wow! That's a great first post. I hope the OP appreciates the answer. For myself, I was interested in the question as I'm working on improving my Bash scripting skills and figured it was long past time I started learning sed and awk.
    My advice would be that you should NEVER attempt to test out a sed command using the -i unless you want to destroy files needlessly. :eek:

    Rather, you should test ONE file to console, to see if it works.

    In other words MAKE IT SIMPLE, just to check out the syntax before actually running it.

    I find that nearly always I am able to work it out for myself. All you have to do is take it piece by piece, slowly but surely, as I did. It is also a very interesting experience and a way to learn more. For some reason the ' with the backslash just doesn't work - perhaps it's a bug?

    Again - test it out but NOT using the -i yet. That should only be used when you are TOTALY sure everything works as expected.

    All excellent advice.

    Inspired by 24365confused's post, I came up with this:
    $ a='link=Sign Out'
    $ echo $a | sed "s:link=Sign Out://a[contains(@href, '/user/logout')]:g"
    //a[contains(@href, '/user/logout')]
    

    Using 0x27 is a neat trick and works fine on my laptop running GNU/Linux but for some reason it doesn't work on my girlfriend's computer (running Mac OS X Tiger 10.4). The above command using double quotes work on both our computers.

    Also using semi-colons instead of forward slashes as the regex delimiter avoids the ugly leaning toothpick syndrome.


  • Advertisement
  • Registered Users, Registered Users 2 Posts: 2 24365confused


    Thanks for the praise - I'm blushing! :o

    The problem with using double quotes in any command which bash is going to send to a program like sed, awk etc is that it will process all the characters within the double quotes. So, for example, if there was an asterisk bash would do something strange, no doubt! That is why they are usually enclosed in single quotes, so bash passes on the data directly unchanged to the command.

    In this case it is ok but it is a thing to keep an eye on.

    Ant
    I noticed you mentioned 0x27. Just for the record, 0x27 doesn't work on mine, only \x27


Advertisement