stringgnuplotcase-conversion

gnuplot - convert a string variable to lowercase


How do you convert a string to lowercase in gnuplot?
This is a gnuplot string handling question.

Example:- I wish to check a user typed parameter in a gnuplot script....

if (tolower(ARG2) == "ohms") {.....

so by accepting "ohms", "Ohms", or "OHMS".

The preference is to not need to use an external "system" command so that the script is more portable. My current best solution is

  arg2 = system("awk 'BEGIN { print toupper(\"".ARG2."\") }'")

and then test the new string variable "arg2", but awk (or other program) may not be generally available on a non unix system, making the gnuplot script less portable.

I cannot see any enhanced gprintf % format specifiers that modifies string presentation - it seems gprintf is only for converting values.


Solution

  • The full function Macro solution (Thanks theozh) has me thinking again of how to implement this as a function. The idea of using a lookup table to convert characters by equating an ordinal number was a great idea. Encapsulating single character case conversion into a function was the start, and then along with recursion, it has made it possible to handle full strings as I had first looked for. I hope this is now a tidy solution for all. Share and enjoy.

    # GNUPLOT string case conversion
    # string_case.gnu   M J Pot, 14/1/2019
    
    # Index lookup table strings
    UCases="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    LCases="abcdefghijklmnopqrstuvwxyz"
    
    # Convert a single character
    # Char to convert is added to string so it is always found to default other chars
    toupperchr(c)=substr( UCases.c, strstrt(LCases.c, c), strstrt(LCases.c, c) )
    tolowerchr(c)=substr( LCases.c, strstrt(UCases.c, c), strstrt(UCases.c, c) )
    
    # Convert whole strings
    # Conversion first char (or return null), and recurse for the remaining
    toupper(s) = s eq ""  ?  ""  :  toupperchr(s[1:1]).toupper(s[2:*])
    tolower(s) = s eq ""  ?  ""  :  tolowerchr(s[1:1]).tolower(s[2:*])
    

    Addition: Improved solution

    This is a re-work of the recursive case conversion as self contained functions. A little more effort has resolved the excessive stack usage of the first solution. I had only been considering strings of single words when I had the problem. Note:- the single character conversion has been made more robust.

    # GNUPLOT string case conversion
    # string_case.gnu   M J Pot, 29/1/2019
    # toupper(), tolower() functions
    
    # Index lookup table strings
    UCases="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    LCases="abcdefghijklmnopqrstuvwxyz"
    
    # Convert a single character
    # Char to convert is added to string so it is always found to default other chars
    # Null strings are returned null
    toupperchr(c)= c eq ""  ?  ""  :  substr( UCases.c, strstrt(LCases.c, c), strstrt(LCases.c, c) )
    tolowerchr(c)= c eq ""  ?  ""  :  substr( LCases.c, strstrt(UCases.c, c), strstrt(UCases.c, c) )
    
    # Divide & conquer
    # A simple linear recursive call uses too much stack for longer strings.
    # This undertakes a binary tree division to make the stack growth order log_2(length)
    toupper(s) = strlen(s) <= 1 ? toupperchr(s) : toupper( substr(s,1,strlen(s)/2) ) . toupper( substr(s,(strlen(s)/2)+1,strlen(s)) ) 
    tolower(s) = strlen(s) <= 1 ? tolowerchr(s) : tolower( substr(s,1,strlen(s)/2) ) . tolower( substr(s,(strlen(s)/2)+1,strlen(s)) )