2
editAppsDotPy() { echo 'from django.apps import AppConfig' >> apps.py echo >> apps.py echo >> apps.py echo "class ${APP_NAME}Config(AppConfig):" >> apps.py echo " name = '${APP_NAME}'" >> apps.py } 

How would you capitalize the variable in the 5th line? I was trying to do it with ${APP_NAME^} but it returns me an error.

15
  • Works fine for me. What error? Commented Jun 3, 2020 at 10:20
  • 1
    @Thomas manage.sh: line 29: ${APP_NAME^}: bad substitution Commented Jun 3, 2020 at 10:23
  • 2
    Which version of bash do you have and what is the she-bang which is on the first line of your script? Commented Jun 3, 2020 at 10:24
  • 3
    Be sure the script is run with Bash and not some other Shell. This case changing expansion is a Bash specific feature. Commented Jun 3, 2020 at 10:25
  • 1
    declare -c APP_NAME="foo"; echo "$APP_NAME" Commented Jun 3, 2020 at 10:42

3 Answers 3

4

Your function rewritten to work with more various shells:

script.sh:

#!/usr/bin/env sh capitalize() { printf '%s' "$1" | head -c 1 | tr [:lower:] [:upper:] printf '%s' "$1" | tail -c '+2' } editAppsDotPy() { cat >> 'app.py' <<EOF from django.apps import AppConfig class $(capitalize "$APP_NAME")Config(AppConfig): name = '$APP_NAME' EOF } APP_NAME='foo' editAppsDotPy 

Demoing:

sh script.sh cat app.py 

Output:

from django.apps import AppConfig class FooConfig(AppConfig): name = 'foo' 
Sign up to request clarification or add additional context in comments.

13 Comments

it capitalizes and writes only the first letter of the variable
Um, isn't that what you asked for? After all, the title of your question is How to capitalize first letter in bash?. You can (and should!) change the title by clicking edit at the bottom left of your question.
@Socowi instead of FooConfig it returns FConfig.
@Sevy Look like MacOS's head command is terminating the input stream. So I wrote it differently by re-injecting the string separately for the remaining unchanged characters. Please try again with this latest version.
There is no guarantee that head will read only as much data as it needs in order to write its requested output.
|
3

Assuming that tr is in your path, the more common parameter substitutions can help you too. Your fifth line could look like the following:

echo "class `tr [:lower:] [:upper:] <<<${APP_NAME:0:1}`${APP_NAME:1}Config(AppConfig):" >> apps.py 

I also tested this in zsh 5.8.

4 Comments

imo the best solution but know my whole code is treated as a string
@Sevy good solution but uses Bash's or Zsh's specific index expansion feature, that does not exist in Ksh or purely POSIX shells.
@LéaGris on top of that, zsh is not POSIX compliant.
As well as <<<"here string" redirection syntax is non-portable feature, not available with POSIX.
1

If your version of bash is too old to support that extension (Like the OS X version), or you're using a shell like zsh that doesn't support it at all, you have to turn to something else. Personally, I like perl (Which I think OS X comes with):

$ perl -ne 'print ucfirst' <<<"foobar" Foobar 

or for something in the middle of a longer string:

$ foo=bar $ echo "foo='$(perl -ne 'print ucfirst' <<<"$foo")'" foo='Bar' 

which works in bash and zsh.

3 Comments

Could you explain me, how does it work with particular situtation?
@Sevy What part? The perl just titlecases its input. Everything else is just basic shell command substitution and herestrings.
I don't know how should it look in my situation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.