gnuplot:使用正则表达式解析字符串

4
请告诉我如何在gnuplot脚本中做到以下两点:
1)解析字符串并从中提取数字和字母/字符串?
2)是否可以使用关联数组以避免使用多个IF语句?
files = system(sprintf("dir /b \"%s*.csv\"", inputPath))

do for [name in files]{

    # MY TROUBLES IS HERE
    [value, typeID] = parse(name, "*[%d%s]*"); # pseudocode
    typesList = {"h": 3600, "m": 60, "s": 1};

    scale = value * typesList[typeID];
    # MY TROUBLES IS ABOVE

    myfunc(y) = y * scale

    outputName = substr(name, 0, strlen(name) - strlen(".csv"))

    inputFullPath = inputPath.name
    outputFullPath = outputPath.outputName.outputExt

    plot inputFullPath using 1:(myfunc($2)) with lines ls 1 notitle
}

在我的情况下,我需要从文件名中获取秒数,格式如下: ...[d=17s]..., ...[d=2m]..., ...[d=15h]... 等等。
在更复杂的情况下:...[d = 2h7m31s]... (这是一个普遍情况,对我可能没有用处,但了解如何解决它会很有趣)。

gnuplot 不适用于解析字符字符串,因此您需要改变方法。您可以将此信息放在文件开头(以秒为单位),读取它,然后跳过第一行读取数据。或者,因为根据 dir 您正在使用 Windows,您可以从 GnuWin32 存储库(http://gnuwin32.sourceforge.net/packages.html)下载 grepsed 实用程序,并阅读如何使用它们的文档。 - Michael
2个回答

7

gnuplot不支持正则表达式,但您可以编写一个函数来从文件名中提取以秒为单位的时间。如果您的文件名和时间戳有严格的格式,例如像"...[d=2h7m31s]...",则可以使用以下代码。否则,您需要相应地进行调整。

  1. 首先使用 strstrt() 提取出 2h7m31s 部分
  2. 使用 strptime() 解析它
  3. 使用 int() 将它转换为整数

脚本:

### parse special time string

NAME = "Filename[d=2h7m31s].csv"

TimeExtract(s) = int(strptime("%Hh%Mm%Ss",s[strstrt(s,'[d=')+3:strstrt(s,']')-1]))
    
print TimeExtract(NAME)
### end of code

结果:

7651

补充:

以下代码也适用于其他可能性,只要序列为...[d=..h..m..s]...

更新:(希望是最终版本)

时间格式%H在24小时后会循环(实际上,在此处为100小时)。因此,为了获取正确的秒数,应该使用%tH%tM%tS(查看help time_specifiers)。有了这个,你还可以解析奇怪的格式,如[d=100h100m100s]

脚本:

### parse special time string
reset session

$Data <<EOD
abcd[d=31s]somethingelse.csv
efghi[d=7m]somethingelse.csv
jklmn[d=2h]somethingelse.csv
op[d=7m31s]somethingelse.csv
qr[d=2h31s]somethingelse.csv
uvw[d=2h7m]somethingelse.csv
xyz[d=2h7m31s]somethingelse.csv
aaa[d=100h100m100s]strangetime.csv
EOD

getTimeString(s) = s[strstrt(s,'[d=')+3:strstrt(s,']')-1]

getTimeFormat(s) = \
    (strstrt(getTimeString(s),'h') ? '%tHh' : '').\
    (strstrt(getTimeString(s),'m') ? '%tMm' : '').\
    (strstrt(getTimeString(s),'s') ? '%tSs' : '')

extractTime(s) = int(strptime(getTimeFormat(s),getTimeString(s)))

do for [i=1:|$Data|] {
    s = $Data[i]
    print sprintf("% 12s   %d",getTimeString(s),extractTime(s))
}
### end of script

结果:

         31s   31
          7m   420
          2h   7200
       7m31s   451
       2h31s   7231
        2h7m   7620
     2h7m31s   7651
100h100m100s   366100

好的!那么,日期是否为非严格格式,就像上面的例子一样? - Zhihar

1
我通过搜索同样的目标来到了你的文章:在文件中查找一个模式,直到空格为止,以获取可在gnuplot中使用的字符串列表。
new_plan.txt:
blabla CIC1 blabla
blabla CIC2.2-prod blabla
blabla CIC1 blabla
etc.

^ 要解析的文件 ^

gnuplot> system("cat new_plan.txt| sed -n -E 's/^.*(CIC\\S*).*$/\\1/p' |sort |uniq")

结果:

CIC1 
CIC2.2-prod

让人厌烦的事情是不要忘记在字符串中添加反斜杠\,以便gnuplot可以通过系统调用调用它。

我没有回答你的标题问题,但回答了你的最后一条评论:

(这是一个普遍情况,对我来说不太可能有用,但了解如何解决它会很有趣)


当然,您始终可以进行系统调用并使用外部工具来处理数据或字符串。这假定您已安装了sed、awk或其他工具,这对于Linux用户可能是正确的,但通常不适用于其他用户。 - theozh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接