Dan L
Dan L

Reputation: 4439

Shell script: escaping list of parameters including hash symbol (#)

I wrote a custom shell script for myself to make it easier for me to commit code to Github.

Recently, I wanted to start using Github's ability to automatically close issues by including their number in the commit message:

# Would automatically close #1 on push
git add .
git commit -m "Closes issue #1 ..."
git push

However, the way my script is set up, it grabs all the parameters using $* but that automatically removes anything after the # symbol, because that's a comment in shell scripts.

commit() {
  # Print out commands for user to see
  echo "=> git add ."
  echo "=> git commit -m '$*'"
  echo "=> git push --set-upstream origin $current_branch"

  # Actually execute commands
  git add .
  git commit -m "$*"
  git push --set-upstream origin $current_branch
}

Now I CAN do commit 'Closes issue #1 ...' with the wrapping quotes, but that's slightly annoying...I specifically setup my script so I could easily write: commit Whatever message I want to put in here...

I've looked over the man pages and done some SO searching, but I can't find anything about the specific issue of escaping # symbols as a parameter.

Is this even possible?

Upvotes: 1

Views: 1075

Answers (2)

that other guy
that other guy

Reputation: 123410

Anything after the # is interpreted by the shell as a comment, so it will not passed to the function. This happens before the function is executed. There is nothing the function can do to prevent this.

There are two canonical ways of doing this:

  • Just require quoting. Every single Unix tool that accepts command line parameters requires this.
  • Have the program read the commit from stdin instead with read -r input. You can then run just commit and type in the message.

These are both good solutions because they're simple, familiar, transparent, robust, idiomatic Unix that is straight forward to reason about. It's always better to work with Unix than against it.

However, if you instead prefer a complex, unfamiliar, opaque, fragile special case, you can kludge it with magic aliases and history:

commit() {
  echo "You wrote: $(HISTTIMEFORMAT= history 1 | cut -d ' ' -f 2-)"
}
alias commit="commit # "

Here's an example of this:

$ commit This is text with #comments and mismatched 'quotes and * and $(expansions)
You wrote: commit This is text with #comments and mismatched 'quotes and * and $(expansions)

Upvotes: 3

Yuri G.
Yuri G.

Reputation: 4648

just played a little with it

the script

commit() {
  echo "$*"
}

script's usage and output

➜  ~ commit "whatever you want #1 for some reason" 
whatever you want #1 for some reason
➜  ~ commit 'whatever you want #1 for some reason'
whatever you want #1 for some reason
➜  ~ commit whatever you want \#1 for some reason 
whatever you want #1 for some reason
➜  ~ commit whatever you want #1 for some reason 
whatever you want
➜  ~ 

so if you don't want to quote the message you need to escape the hash with a \ (backslash), that is actually a regular escape character

Upvotes: 1

Related Questions