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.

Sevy
  • 93
  • 10

3 Answers3

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'
Léa Gris
  • 17,497
  • 4
  • 32
  • 41
  • it capitalizes and writes only the first letter of the variable – Sevy Jun 03 '20 at 11:09
  • 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 Jun 03 '20 at 11:10
  • @Socowi instead of FooConfig it returns FConfig. – Sevy Jun 03 '20 at 11:15
  • I cannot reproduce your problem. `APP_NAME=foo editAppsDotPy; cat app.py` prints `fooConfig(...` (unchanged because this is the 4th line) and `name = 'Foo'` (correctly capitalized in the 5th line). – Socowi Jun 03 '20 at 11:23
  • your code returns it https://pastebin.com/4Kgke1Su – Sevy Jun 03 '20 at 11:33
  • @Sevy modified the `capitalize` function to use `cat` for the reminder of the string. Can you try again with this version? – Léa Gris Jun 03 '20 at 11:39
  • @Sevy That is really strange. I get the correct output in dash 0.5.10.2 and bash 4.4.12, 4.4.20, and 5.0.3 on my system and [these](https://www.tutorialspoint.com/execute_bash_online.php) [two](https://repl.it/repls/MammothBumpyPlans#main.sh) online IDEs. Are you sure you correctly copied the script posted in this answer? It is suspicious that the 4th line (which just printed the unmodified variable `$APP_NAME` in the first version of this answer) returned something different than assigned. – Socowi Jun 03 '20 at 11:44
  • still the same problem. – Sevy Jun 03 '20 at 11:50
  • @Socowi yes. I'm pretty sure that I copied everything properly. I did it even for few times. – Sevy Jun 03 '20 at 11:54
  • changing shebang, indentation etc. also does nothing. – Sevy Jun 03 '20 at 11:54
  • 1
    @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. – Léa Gris Jun 03 '20 at 12:05
  • 2
    There is no guarantee that `head` will read *only* as much data as it needs in order to write its requested output. – chepner Jun 03 '20 at 12:06
  • @LéaGris finally it works. thank you guys. – Sevy Jun 03 '20 at 12:07
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.

lab9
  • 596
  • 2
  • 8
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.

Shawn
  • 47,241
  • 3
  • 26
  • 60