0

I've written the following bash script that utilizes awk, the aim is to set the first character to lower case. The script works mostly fine, however I'm adding an extra space when I concat the two values. Any ideas how to remove this errant space?

Script:

#!/bin/bash

foo="MyCamelCaseValue" 
awk '{s=tolower(substr($1,1,1))}{g=substr($1,2,length($1))}{print s,g}' <<<$foo

Output:

m yCamelCaseValue

edit:

Please see discussion from Bobdylan and RavinderSingh13 on accepted answer as it highlights issues with default MacOs bash version.

bash --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19) Copyright (C) 2007 Free Software Foundation, Inc.

Inian
  • 80,270
  • 14
  • 142
  • 161
WillBroadbent
  • 804
  • 2
  • 8
  • 22
  • 1
    Use `{print s""g}` – Wiktor Stribiżew Sep 18 '20 at 09:05
  • Does this answer your question? [Extra space in awk output](https://stackoverflow.com/questions/9511803/extra-space-in-awk-output) – Wiktor Stribiżew Sep 18 '20 at 09:06
  • Also, you may use Bash for it, [uppercase first character in a variable with bash](https://stackoverflow.com/questions/12487424/uppercase-first-character-in-a-variable-with-bash). – Wiktor Stribiżew Sep 18 '20 at 09:08
  • Or use `echo "${foo,}"` – bob dylan Sep 18 '20 at 09:12
  • I tried echo "${foo,}" an error: ./test.sh: line 4: ${foo,}: bad substitution – WillBroadbent Sep 18 '20 at 09:14
  • Show me the output? What bash version are you on? line 1 = `foo="MyCamelCaseValue"` line 2 = `echo "${foo,}"` = works – bob dylan Sep 18 '20 at 09:15
  • The script I had for the echo ${foo,} solution: line 1= #!/bin/bash line 2 = foo="MyCamelCaseValue" line 3 = echo "${foo,}" Gives output: ./test.sh: line 3: ${foo,}: bad substitution (Sorry for not posting whole script, I realise the line error is useless without) – WillBroadbent Sep 18 '20 at 09:20
  • @WillBroadbent, if you could work without `awk` then I would say you could go with bash answer that should be the one, kindly do confirm, once you confirm I will delete my answer then. – RavinderSingh13 Sep 18 '20 at 09:26
  • @WillBroadbent - I put this in the wrong comment box - see https://pastebin.com/VbgHRM5t – bob dylan Sep 18 '20 at 09:28
  • 2
    @RavinderSingh13 - I was typing before the post got deleted. Anyway - yes I agree. But I was more on the principal that yes it's technically a solution - but it's not the most elegant way. His attempt was an attempt - but doesn't mean it can't be re-written and improved upon wholesale. :) – bob dylan Sep 18 '20 at 09:30
  • @bobdylan I've just tried that exact pastebin and im still getting the same error. It could be my bash version i'm not sure. bash --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19) Copyright (C) 2007 Free Software Foundation, Inc. – WillBroadbent Sep 18 '20 at 09:31
  • 2
    Using a 13+ year old version is kinda the problem there to be fair..... But I agreed the version might be an issue (dunno when it was introduced exactly) – bob dylan Sep 18 '20 at 09:35
  • @bobdylan, so why not un-delete the working(awk) solution then(since OP is having OLD version of bash because of that only else there is NO reason of undoing it, though I am still OK to have it in deleted form too if we agree on it) :) I am asking to myself, what you say? – RavinderSingh13 Sep 18 '20 at 09:36
  • 1
    Sure go for it - I've submitted a response as an alternative and we're in agreement anyway. If on a 15 year old version (i.e. macos default) and you can't upgrade then by all means do the awk etc. If not then use a proper version of bash (which you should be doing) and do it this way. Leaving this post now as I've already spent too long on it ;) – bob dylan Sep 18 '20 at 09:37
  • 1
    I'd happily upgrade, problem is i'm creating this script to be used by other mac users in my company. The solution is to just package so they dont have to worry about versions but I'd rather it worked with the default settings their setups have. Sounds dumb, sorry folks! I appreciate all your help :) – WillBroadbent Sep 18 '20 at 09:39

1 Answers1

5

You were close and good try, you need not get length of line here, substr is intelligent enough to get the rest of the length of you mention a character position and don't give till where it should print(length value). Could you please try following.

(Usually these kind of problems could be solved by bash itself but when OP tried bash solution provided by @bob dylan its having issues because of OLD version of BASH, hence I am undeleting this one which is working for OP)

echo "$foo" | awk '{print tolower(substr($0,1,1)) substr($0,2)}' Input_file

Explanation:

  • Use substr function of awk to get sub-strings in current line.
  • Then grab the very first letter by substr($0,1,1) and wrap it inside tolower to make it in small case.
  • Now print rest of the line(since first character is already being captures by previous substr) by doing `substr($0,2) this will print from 2nd character to last of line.


EDIT by @bob dylan:

https://www.shell-tips.com/mac/upgrade-bash/

MacOS comes with an older version of bash. However if you're on 4+ you should be able to use the native bash function to translate the first character from upper to lower:

$ bash --version
GNU bash, version 4.4.19(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ cat foo.sh
#!/bin/bash
foo="MyCamelCaseValue"
echo "${foo,}"
$ bash foo.sh
myCamelCaseValue

Further examples for the whole string, to lower, to upper etc.

$ echo $foo
myCamelCaseValue
echo "${foo,}"
myCamelCaseValue
$ echo "${foo,,}"
mycamelcasevalue
$ echo "${foo^}"
MyCamelCaseValue
$ echo "${foo^^}"
MYCAMELCASEVALUE
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
  • 2
    Worked perfectly :) I'll accept the answer when able to – WillBroadbent Sep 18 '20 at 09:08
  • Because you're basically trying to pipe from input and do some funkiness with regards to length. Doing just `"${foo,}"` = the same as saying "tr the first character from upper to lower) without needing an awk and length check, garbling etc. – bob dylan Sep 18 '20 at 09:21
  • And mine does. You're on about file wide etc, but his example gives a specific value to $foo and you make an assumption - my point is ops solution might work - but it's overkill for a native function in bash – bob dylan Sep 18 '20 at 09:26
  • @bobdylan, yeah I add a note with OP's OLD bash version thing we should be good here. – RavinderSingh13 Sep 18 '20 at 09:40
  • @RavinderSingh13 - I've submitted an edit to your post (since I don't care about scores) which the better solution since both are ok in different scenarios. Once approved I'll switch my vote around. – bob dylan Sep 18 '20 at 09:42
  • 1
    Is it beneficial if I edit the original question and mention the older version of Bash and the Mac setup? edit: I see the answer reflects this info, i'll leave the question unedited – WillBroadbent Sep 18 '20 at 09:43
  • @WillBroadbent, yes please you could edit it in your question's description that will future users better understanding on your question. – RavinderSingh13 Sep 18 '20 at 09:43
  • 2
    All sorted :) got there in the end! – bob dylan Sep 18 '20 at 09:44