gnuplot - 将字符串变量转换为小写

时间:2017-08-21 23:38:44

标签: string gnuplot case-conversion

如何在gnuplot中将字符串转换为小写?
这是一个gnuplot字符串处理问题。

示例: - 我希望在gnuplot脚本中检查用户输入的参数....

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

所以接受“欧姆”,“欧姆”或“OHMS”。

首选是不需要使用外部“系统”命令,以便脚本更具可移植性。我目前最好的解决方案是

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

然后测试新的字符串变量“arg2”,但是awk(或其他程序)可能在非unix系统上通常不可用,这使得gnuplot脚本的可移植性降低。

我看不到任何修改字符串表示的增强gprintf%格式说明符 - 似乎gprintf仅用于转换值。

3 个答案:

答案 0 :(得分:1)

我不知道gnuplot提供大写或小写功能。 下面的尝试不是一个函数,而是一个宏,该宏将字符串变量w转换为大写或小写,而无需使用OP中的外部工具。在列表中找不到的字符保持不变。可能还有改进的空间,但也许对某些人还是有帮助的。

### gnuplot implementation of uppercase and lowercase
reset session

Cases= "ABCDEFGHIJKLMNOPQRSTUVWXYZ".\
       "abcdefghijklmnopqrstuvwxyz"

uppercase = 'CaseLen=strlen(Cases)/2;\
    wc = ""; \
    do for [i=1:strlen(w)] { \
        tmp1 = substr(w,i,i); \
        tmp2 = strstrt(Cases,tmp1); \
        wc = (tmp2 == 0) ? wc = wc.tmp1 : \
        (tmp2 > CaseLen) ? (tmp2=tmp2-CaseLen, \
        wc.substr(Cases,tmp2,tmp2)) : wc.substr(Cases,tmp2,tmp2);\
    }; w = wc'

lowercase = 'CaseLen=strlen(Cases)/2;\
    wc = ""; \
    do for [i=1:strlen(w)] { \
        tmp1 = substr(w,i,i); \
        tmp2 = strstrt(Cases,tmp1); \
        wc = (tmp2 == 0) ? wc.tmp1 : \
        (tmp2 < CaseLen) ? (tmp2=tmp2+CaseLen, \
        wc.substr(Cases,tmp2,tmp2)) : wc.substr(Cases,tmp2,tmp2);\
    }; w = wc'

# put your string into variable w
w = "...thE qUick brOWn foX jUmPs oVeR The LazY Dog!"
print w
# run the macro uppercase and variable w will we converted to uppercase
@uppercase
print w

# run the macro lowercase and variable w will we converted to lowercase
@lowercase
print w

### end of code

输出:

...thE qUick brOWn foX jUmPs oVeR The LazY Dog!
...THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!
...the quick brown fox jumps over the lazy dog!

添加:改进的版本

我想这就是SO的精神...一起找到最佳解决方案:-)。 @mjp,使用了关于在末尾添加字符的好主意,以及我的“滥用”求和表达式sum作为循环的“新”主意,从而避免了递归。后续解决方案对于递归解决方案具有的字符串没有247个字符的限制(至少在我的计算机上为247个字符)。我希望此解决方案不会有严重的限制。

### gnuplot implementation of uppercase and lowercase
# theozh, 14.01.2014
reset session

UpperCases= "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
LowerCases= "abcdefghijklmnopqrstuvwxyz"

# upper/lowercase for characters
ucchar(c) = substr( UpperCases.c, ucchar_tmp=strstrt(LowerCases.c, c), ucchar_tmp)
lcchar(c) = substr( LowerCases.c, lcchar_tmp=strstrt(UpperCases.c, c), lcchar_tmp)

# upper/lowercase for strings
uc(s) = ((sum[uc_i=1:strlen(s)] (uc_tmp=ucchar(substr(s,uc_i,uc_i)), uc_i>1 ? (uc_w=uc_w.uc_tmp,1):uc_w=uc_tmp,1)),uc_w)
lc(s) = ((sum[lc_i=1:strlen(s)] (lc_tmp=lcchar(substr(s,lc_i,lc_i)), lc_i>1 ? (lc_w=lc_w.lc_tmp,1):lc_w=lc_tmp,1)),lc_w)

s = "...thE qUick brOWn foX jUmPs oVeR The LazY Dog!"
print s
print uc(s)
print lc(s)
### end of code

答案 1 :(得分:1)

全功能宏解决方案(感谢theozh)让我再次思考如何将其实现为功能。使用查找表通过等于序数来转换字符的想法是一个好主意。首先将单个字符的大小写转换封装到一个函数中,然后再进行递归,这使得处理我最初寻找的完整字符串成为可能。我希望这现在是所有人的一个整洁的解决方案。分享并享受。

# 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:*])

添加:改进的解决方案

这是对递归案例转换作为自包含函数的重做。稍加努力即可解决第一个解决方案过多的堆栈使用情况。当我遇到问题时,我只是在考虑一个单词的字符串。注意:-单字符转换已变得更加可靠。

# 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)) ) 

答案 2 :(得分:0)

当希望将独立于大小写的字符串变量与已知字符串常量进行比较时,只需要转换一个字符子集。这不是gnuplot中案例转换的一般情况的答案,但可能适用于许多情况。

arg2 = ARG2
# As we want limited comparisons strstrt(”string”, ”key”) can be used....
# Substitute the first occurrence of a character [pat], with another character [repl]
# Can be used to convert an expected word's case, one character at a time
subchr(src, pat, repl) = strstrt(src, pat)?src[*:strstrt(src, pat)-1].repl.src[strstrt(src, pat)+1:*]:src
arg2 = subchr(arg2, "o", "O")
arg2 = subchr(arg2, "h", "H")
arg2 = subchr(arg2, "m", "M")
arg2 = subchr(arg2, "s", "S")
arg2 = subchr(arg2, "d", "D")
arg2 = subchr(arg2, "b", "B")
if ( arg2[1:2] eq "DB" ) {
  # In terms of dB
  .....
  }
else {
  if ( arg2 eq "OHMS" ) {
    .....
    }
  }

解决方案是编写一个gnuplot字符串函数subchr(),该函数替换单个匹配字符,仅在找到时(三元组?),并为每个要转换的字符调用它。幸运的是,gnuplot字符串范围说明符在(0)之前和之后(stringlength + 1)索引时表现得很好,为该区域返回null。这允许我们返回每个字符升级后的字符串。

这避免了对诸如awk等程序的系统()调用的需要。

相关问题