3

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

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

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

所以通过接受“ohms”、“Ohms”或“OHMS”。

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

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

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

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

4

3 回答 3

2

完整的功能宏解决方案(感谢 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)) ) 
于 2019-01-14T01:17:40.117 回答
2

我不知道 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.2019
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

编辑:(2022 年 1 月)我再次偶然发现我的旧帖子,并认为它可以进一步简化。并且更多字符被添加到查找字符串中。

代码:

### uppercase/lowercase function for gnuplot
reset session

UpperCases= "ABCDEFGHIJKLMNOPQRSTUVWXYZÄÁÂÀËÉÊÈÏÍÎÌÖÓÔÒÜÚÛÙŸÝ"
LowerCases= "abcdefghijklmnopqrstuvwxyzäáâàëéêèïíîìöóôòüúûùÿý"

# upper/lowercase for characters
ucc(c) = ((ucc_i=strstrt(LowerCases, c)) ? UpperCases[ucc_i:ucc_i] : c)
lcc(c) = ((lcc_i=strstrt(UpperCases, c)) ? LowerCases[lcc_i:lcc_i] : c)

# upper/lowercase for strings
uc(s) = (uc_s='', sum[uc_i=1:strlen(s)] (uc_s=uc_s.ucc(s[uc_i:uc_i]),1),uc_s)
lc(s) = (lc_s='', sum[lc_i=1:strlen(s)] (lc_s=lc_s.lcc(s[lc_i:lc_i]),1),lc_s)

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

结果:

Input:     ...thE qUick brOWn foX jUmPs oVeR The LazY Dog!
Uppercase: ...THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG!
Lowercase: ...the quick brown fox jumps over the lazy dog!
于 2019-01-11T23:05:53.357 回答
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 等程序的 system() 调用的需要。

于 2017-09-11T10:43:07.780 回答