You are not logged in.

#1 2018-12-08 22:36:59

MikeW
Member
Registered: 2011-10-19
Posts: 64

[SOLVED] bash - lowercase behavior

I was playing around with bash scripting trying to learn a bit more about bash than I currently know. However I ran into some behavior I don't fully understand.

Lets say we want to make a word lower case. After some searching I came up with an option using tr.

This version works as expected.

 word="$(tr "A-Z" "a-z" <<< "$1")"  

According to shellcheck this should be changed to use :upper, :lower classes.

        word="$(tr "A-Z" "a-z" <<< "$1")"   
                   ^---^ SC2019: Use '[:upper:]' to support accents and foreign alphabets.
                         ^---^ SC2018: Use '[:lower:]' to support accents and foreign alphabets.

I tried this but it does not work. So I am now curious why it doesn't work.

 word="$(tr "[:upper]" "[:lower]" <<< "$1")"   

Last edited by MikeW (2018-12-08 23:03:02)

Offline

#2 2018-12-08 22:41:32

N_BaH
Member
Registered: 2015-12-30
Posts: 20

Re: [SOLVED] bash - lowercase behavior

word="${1,,}"

done!
or

declare -l anotherWord="$1"

done! again wink

Last edited by N_BaH (2018-12-08 22:43:51)

Offline

#3 2018-12-08 22:41:52

jasonwryan
Anarchist
From: .nz
Registered: 2009-05-09
Posts: 26,205
Website

Re: [SOLVED] bash - lowercase behavior

In bash you don't need an additional process/program: you can use parameter expansion: printf "%s\n" "${word,,}"


Arch + dwm   •   Mercurial repos  •   Github

Registered Linux User #482438

Offline

#4 2018-12-08 22:51:30

MikeW
Member
Registered: 2011-10-19
Posts: 64

Re: [SOLVED] bash - lowercase behavior

N_BaH wrote:
word="${1,,}"

done!
or

declare -l anotherWord="$1"

done! again wink

I actually tried this one first and I was getting an error. Which is why I moved onto the tr version. Now I see that it was just that I had a '$' inside the brackets. Thanks for this, much simpler now. 

test_lower: line 3: ${$1,,}: bad substitution

Offline

#5 2018-12-08 23:02:18

MikeW
Member
Registered: 2011-10-19
Posts: 64

Re: [SOLVED] bash - lowercase behavior

jasonwryan wrote:

In bash you don't need an additional process/program: you can use parameter expansion: printf "%s\n" "${word,,}"

This is something I need to read up on more. Just found the parameter expansion section of the man page. Going to mark this as solved, grab a coffee and start reading. smile

Offline

#6 2018-12-09 01:21:39

eschwartz
Trusted User/Bug Wrangler
Registered: 2014-08-08
Posts: 2,535

Re: [SOLVED] bash - lowercase behavior

MikeW wrote:

According to shellcheck this should be changed to use :upper, :lower classes.

        word="$(tr "A-Z" "a-z" <<< "$1")"   
                   ^---^ SC2019: Use '[:upper:]' to support accents and foreign alphabets.
                         ^---^ SC2018: Use '[:lower:]' to support accents and foreign alphabets.

I tried this but it does not work. So I am now curious why it doesn't work.

 word="$(tr "[:upper]" "[:lower]" <<< "$1")"   

While you have been rightly recommended to bash 4.x "Case  modification" for this, it is worth noting that this is only valid in bash 4 and not earlier versions of bash (such as the 3.x one built into macOS which Apple will not update), and also not in POSIX sh scripts (which have the shebang #!/bin/sh rather than #!/bin/bash).

That being the case, and also because in general this is useful, reusable information about how applications in general work, I think you would benefit from an explanation about why the command did not work. It should have worked, regardless of how slow and inefficient it is to subprocess out to an external command, and this is therefore valuable information.

To this end, I would like to point out that you typoed the command.

The classes it refers to are "character classes", as defined by POSIX: http://pubs.opengroup.org/onlinepubs/96 … g_09_03_05 Also referred to rather a lot in any decent tutorial about regular expressions.

Many applications can use these for things which parse and modify characters, and they are defined as [:name:], where the : on both sides is important, and "name" is the type of class. Particularly useful classes are "alpha", "digit", and "space".

You forgot the : on the right-hand side, which is why the tr invocation you used did not work.

...

Having a proper understanding of character classes will allow you to do cool things with tr which you cannot do using bash's case modification operator alone. Also, bash itself, as a program with support for character parsing and modification, supports character classes too: anywhere that you can use ranges like [a-z], you can also use ranges like [[:alpha:]] -- but note that the brackets are doubled, the outer ones mean "match any one of these characters" and the inner ones mean "this is a character class that expands to all members of the class".


Managing AUR repos The Right Way -- aurpublish (now a standalone tool)

Offline

#7 2018-12-09 06:41:15

MikeW
Member
Registered: 2011-10-19
Posts: 64

Re: [SOLVED] bash - lowercase behavior

Thanks for your detailed response.

eschwartz wrote:

While you have been rightly recommended to bash 4.x "Case  modification" for this, it is worth noting that this is only valid in bash 4 and not earlier versions of bash (such as the 3.x one built into macOS which Apple will not update), and also not in POSIX sh scripts (which have the shebang #!/bin/sh rather than #!/bin/bash).

I'm trying to decide if compatibility with 3.x actually matters. I'm not sure it does in my situation. After spending an entire career dealing with Windows, and occasionally Mac's I am retired now. smile After retiring I kicked Windows to the curb since it wasn't something I needed anymore. I got tied to Windows mainly due to the working from home thing from time to time. Now I fully switched over to Linux which I have dabbled in a lot over the years. Its now a hobby learning and understanding the OS that I am running now. Of course if I start contributing to projects or sharing my scripts I may have to rethink the compatibility thing again.

eschwartz wrote:

To this end, I would like to point out that you typoed the command.

Thanks for this it all makes sense now!

eschwartz wrote:

Having a proper understanding of character classes will allow you to do cool things with tr which you cannot do using bash's case modification operator alone. Also, bash itself, as a program with support for character parsing and modification, supports character classes too: anywhere that you can use ranges like [a-z], you can also use ranges like [[:alpha:]] -- but note that the brackets are doubled, the outer ones mean "match any one of these characters" and the inner ones mean "this is a character class that expands to all members of the class".

Regex is something else I have dabbled with over the years. Writing test automation code for windows I found myself pulling out the regex tool box from time to time. I never got that deep into it though. Now that I have time I may have to start diggging a little deeper. smile

Offline

Board footer

Powered by FluxBB