gnuplot - преобразовать строковую переменную в нижний регистр
Как преобразовать строку в нижний регистр в gnuplot?
Это вопрос об обработке строк в gnuplot.
Пример:- Я хочу проверить введенный пользователем параметр в скрипте gnuplot....
if (tolower(ARG2) == "ohms") {.....
таким образом, принимая "ом", "ом" или "омс".
Предпочтение состоит в том, чтобы не использовать внешнюю "системную" команду, чтобы скрипт был более переносимым. Мое текущее лучшее решение
arg2 = system("awk 'BEGIN { print toupper(\"".ARG2."\") }'")
и затем протестируйте новую строковую переменную "arg2", но awk (или другая программа) могут быть недоступны в не-unix-системах, что делает сценарий gnuplot менее переносимым.
Я не вижу никаких расширенных спецификаторов формата gprintf%, которые изменяют представление строки - кажется, что gprintf предназначен только для преобразования значений.
1 ответ
При желании сравнить строковую переменную, независимую от регистра, с известной строковой константой, необходимо преобразовать только подмножество символов. Это не ответ на общую ситуацию преобразования регистра в 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), возвращая ноль для этой области. Это позволяет нам возвращать строку с каждым обновленным символом.
Это позволяет избежать необходимости вызова system() таких программ, как awk и т. Д.
Я не знаю, что 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
Полнофункциональное Макро-решение (Спасибо, 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)) )