12

Im having a bit of trouble putting together a bash script im working on

Here is the code im using.

cat /crawler/bc_daemon.php | sed "s/PORT2/${PORT}/ig" | sed 's/IP2/IPADDRESS/ig' | \
   sed 's/USER2/USER/ig' | sed 's/PASS2/PASSWORD/ig' > bc_daemon.php

cat /crawler/bc_layout.php | sed "s/GITHUB/${REPO}/ig" | sed "s/COINNAME/${NAME}/ig" > bc_layout.php

The odd thing is the lines work individually out of the script. but when inside the script i get this

sed: -e expression #1, char 17: unknown option to `s'

I am using '' when it can take it literally and "" when it needs to print the variable

It seems to me this should be working. But im lost as to where my error is

codeforester
  • 39,467
  • 16
  • 112
  • 140
user3566292
  • 125
  • 1
  • 1
  • 4
  • 2
    I'm going to assume `REPO` has slashes in it and that that is prematurely terminating your `s///` command. Try using a different delimiter `s!!!` or `s@@@` or something that isn't going to be in the `REPO` value. – Etan Reisner Jul 11 '14 at 20:22
  • 2
    FYI, BashFAQ #21 suggests methods of doing replacement that don't have `sed`'s limitation of requiring a delimiter character that doesn't exist in content. See http://mywiki.wooledge.org/BashFAQ/021 – Charles Duffy Jul 11 '14 at 20:27
  • @ Etan Reisner that was it. Thank you very much. Didnt think about the fact the REPO is a url so has /'s in it. Thank you everyone for your help :) – user3566292 Jul 11 '14 at 21:07

4 Answers4

30

One of the values contains a slash. You need to escape it, or use a different delimiter.

Additionally, you are needlessly stringing together multiple invocations where a single one would do. The cat is also useless.

sed -e "s@PORT2@${PORT}@ig" \
    -e 's/IP2/IPADDRESS/ig' \ 
    -e 's/USER2/USER/ig' \
    -e 's/PASS2/PASSWORD/ig'  /crawler/bc_daemon.php > bc_daemon.php

Unfortunately, not all sed dialects are compatible. If yours doesn't like multiple -e options, try a single string of newline-separated sed commands. I'm providing the second script in this syntax as an example.

sed "s!GITHUB!${REPO}!ig
    s!COINNAME!${NAME}!ig"  /crawler/bc_layout.php > bc_layout.php

If your values could contain @ or ! as well, you will need to pick a different delimiter. Any nonalphanumeric ASCII character will do, but backslash and quotes are obviously problematic.

tripleee
  • 175,061
  • 34
  • 275
  • 318
5

One possible thing is that i may not be recognized by the sed you use that you have no choice but to remove it:

sed "s/GITHUB/${REPO}/g"

(kunwar.sangram suggests that the uppercase I may be recognized instead.)

Another thing is that some of your variables may contain the delimiter you use to s, so perhaps trying to use another delimiter may fix it:

sed "s|GITHUB|${REPO}|ig"
Community
  • 1
  • 1
konsolebox
  • 72,135
  • 12
  • 99
  • 105
5

Leave the cats out of this; they're happier curled up in a corner and left in peace. The first sed in each pipeline can read the file.

You should be able to combine those separate sed commands into one per pipeline, too. That is, your current command:

cat /crawler/bc_daemon.php |
sed "s/PORT2/${PORT}/ig" |
sed 's/IP2/IPADDRESS/ig' |
sed 's/USER2/USER/ig' |
sed 's/PASS2/PASSWORD/ig' > bc_daemon.php

should be:

sed -e "s/PORT2/${PORT}/ig" \
    -e 's/IP2/IPADDRESS/ig' \
    -e 's/USER2/USER/ig' \
    -e 's/PASS2/PASSWORD/ig' \
    /crawler/bc_daemon.php > bc_daemon.php

This ignores the issue with the unknown option to the s/// command, which is probably might be referring to the i flag. The GNU sed man page on Linux doesn't list that, but the online GNU sed manual does list both i and I as options for case-insensitivity, so that should not be the problem. One other possibility is that the expansion of ${PORT} contains a slash; that could cause the error you're seeing (or, that the problem is in the second pipeline instead of the first).

If you are not using GNU sed (and the error suggests that you might not be), you might need to brute-force the patterns.

sed -e "s/[pP][oO][rR][tT]2/${PORT}/g" \
    -e 's/[iI][pP]2/IPADDRESS/g' \
    -e 's/[uU][sS][eE][rR]2/USER/g' \
    -e 's/[pP][aA][sS][sS]2/PASSWORD/g' \
    /crawler/bc_daemon.php > bc_daemon.php

Note that both these pipelines will fail horribly if the current directory is /crawler because the output redirection will clobber the input file before the command is executed.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Given that the OP is on Ubunutu and states that the commands work outside of a script, I'd say that `i` is probably not the issue. If the replacement string does contain slashes, all bets are off as to what characters end up getting misinterpreted as `s` options. Try something like `sed 's/a/b/c/ig' <<<'a'` - note how the error message doesn't _name_ the offending option. – mklement0 Jul 11 '14 at 20:54
  • The real problem, it seems, was in the other pipeline, and was a slash in the replacement string there (which I mentioned as a possible issue). The case-insensitivity stuff isn't dreadfully relevant, but the UUOC and "one `sed` command is enough" and "beware if current directory is `/crawler`" are all valid pieces of advice, even if not dreadfully up-vote-worthy. – Jonathan Leffler Jul 11 '14 at 21:34
  • Yes, you did mention the slashes issue. I was trying to point out that `unknown option to the s/// command, which is probably referring to the i flag` and `not using GNU` were red herrings. – mklement0 Jul 11 '14 at 21:45
  • Thanks for updating; you're right about your answer containing valid advice; +1. – mklement0 Jul 11 '14 at 23:41
-1

Try

cat /crawler/bc_layout.php | \
sed "s/GITHUB/${REPO}/gI" | \
sed "s/COINNAME/${NAME}/gI" > bc_layout.php