Nick lK
Nick lK

Reputation: 2647

Escape value in echo statement in Terminal on Mac

So i've been working on adding a few aliases to the .bash_profile to make it easier to set up composer PHP/Composer projects on my Mac.I've gotten very close to completing this but i'm having an issue. I'm trying to output a string to a file i'm creating but the single quotes keep getting removed.

The alias i'm setting up is as follows:

alias sp='touch index.php; echo "<?php  \n\n  require_once __DIR__ . $ '/vendor/autoload.php' ?>;" >> index.php; open/Applications/TextWrangler.app index.php;'

The output i'm getting in the php file is:

<?php  \n\n require_once __DIR__ . $ /vendor/autoload.php \n\n ?>

I've tried escaping using \e and $'string'

But have had no luck.

Upvotes: 1

Views: 843

Answers (1)

Gordon Davisson
Gordon Davisson

Reputation: 126013

Short answer: When doing anything nontrivial, use functions instead of aliases and printf instead of echo.

Long answer: the immediate problem is that quotes don't nest. You're trying to use single-quotes around an alias that contains single-quotes, and that won't work. The shell is parsing your command as containing the single-quoted segment 'touch index.php; echo "<?php \n\n require_once __DIR__ . $ ', followed by the unquoted segment /vendor/autoload.php, followed by the single-quoted segment ' ?>;" >> index.php; open/Applications/TextWrangler.app index.php;' -- it removes the quotes, mashes them together, and assigns the result as the alias.

There are ways to fix this, but they're ugly. Things like alias sp='touch ... $ '"'"'/vendor/... -- here, the first single-quote ends the single-quoted segment, then there's a double-quoted segment containing a single-quote, then the beginning of another single-quoted segment. Bleh.

Really, when defining an alias gets this complicated, you're better off switching to a function. Among other things they don't need to be quoted, so this whole problem is moot:

sp() {
    touch index.php
    echo "<?php  \n\n  require_once __DIR__ . $ '/vendor/autoload.php' ?>;" >> index.php
    open/Applications/TextWrangler.app index.php
}

But as long as I'm making suggestions, I'd make a couple of other changes. First, the touch command isn't doing anything that the redirect isn't going to do anyway, so I'd leave it out. Second, using \n with echo is unpredictable; some versions of echo convert it to newlines, some don't. It's actually changed between different versions of OS X. You're much better off using printf for this, although it's more complicated to use properly. The first argument to printf is a format string that's used to control how the rest of the arguments are printed. The other big difference from echo is that it doesn't automatically add a newline to the end, so you have to do that yourself. I'm assuming you want to put this into the index.php file:

<?php

require_once __DIR__ . $ '/vendor/autoload.php'

?>

There are several ways to do this with printf. Probably the simplest would be to make each line an argument, and use the format string to put a newline after each one:

printf '%s\n' "<?php" "" "require_once __DIR__ . \$ '/vendor/autoload.php'" "" "?>"

But In this case I'd use cat with a here-document. You can do that inside a function (unlike an alias):

sp() {
    cat <<"EOF" >>index.html
<?php

require_once __DIR__ . $ '/vendor/autoload.php'

?>
EOF
    open/Applications/TextWrangler.app index.php
}

If you want cleaner indentation, you can also use <<-"EOF", and then indent the here-doc content with tabs (not spaces).

Upvotes: 4

Related Questions