Command line “设置数据文件分隔符”中的多字符分隔符|||";`不';行不通
我有一个输入文件Command line “设置数据文件分隔符”中的多字符分隔符|||";`不';行不通,command-line,gnuplot,Command Line,Gnuplot,我有一个输入文件example.data,其中三个管道作为分隔符,日期在第一列,还有一些或多或少不可预测的文本在最后一列: 2019-02-01|||123|||345|||567|||Some unpredictable textual data with pipes|, 2019-02-02|||234|||345|||456|||weird symbols @ and commas, and so on. 2019-02-03|||345|||234|||123|||text text t
example.data
,其中三个管道作为分隔符,日期在第一列,还有一些或多或少不可预测的文本在最后一列:
2019-02-01|||123|||345|||567|||Some unpredictable textual data with pipes|,
2019-02-02|||234|||345|||456|||weird symbols @ and commas, and so on.
2019-02-03|||345|||234|||123|||text text text
当我尝试运行下面的gnuplot5脚本时
set terminal png size 400,300
set output 'myplot.png'
set datafile separator "|||"
set xdata time
set timefmt "%Y-%m-%d"
set format x "%y-%m-%d"
plot "example.data" using 1:2 with linespoints
我得到以下错误:
line 8: warning: Skipping data file with no valid points
plot "example.data" using 1:2 with linespoints
^
"time.gnuplot", line 8: x range is invalid
更奇怪的是,如果我把最后一行改成
plot "example.data" using 1:4 with linespoints
然后它就起作用了。它也适用于1:7
和1:10
,但不适用于其他数字。为什么?使用
set datafile separator "chars"
在语法中,字符串不被视为一个长分隔符。相反,引号之间列出的每个字符都会单独成为分隔符。自[Janert,2016]:
如果提供显式字符串,则字符串中的每个字符都将
作为分隔符处理
所以,
set datafile separator "|||"
实际上相当于
set datafile separator "|"
还有一条线
2019-02-05|||123|||456|||789
被视为有十列,其中只有列1、4、7、10是非空的
解决方法 查找不太可能出现在数据集中的其他字符(在下面的示例中,我将假定
\t
)。如果无法使用其他分隔符转储数据集,请使用sed
将| |
替换为\t
:
sed 's/|||/\t/g' example.data > modified.data # in the command line
然后继续
set datafile separator "\t"
然后
修改。数据作为输入。基本上你自己给出了答案
如果可以影响数据中的分隔符,请使用通常不会出现在数据或文本中的分隔符。我一直认为\t
就是为了这个
如果无法影响数据中的分隔符,请使用外部工具(awk、Python、Perl等)修改数据。在这些语言中,它可能是“一行”。gnuplot没有直接替换功能
如果您不想安装外部工具,并且希望确保平台独立性,那么仍然可以使用gnuplot来实现。不仅仅是一个“一行程序”,而且对于gnuplot几乎没有什么是不能做的;-)
编辑:使用@Ethan()输入的简化版本
假设您的数据位于名为$data
的数据集中。以下代码将用\t
替换| |
,并将结果放入$DataOutput
### Replace string in dataset
reset session
$Data <<EOD
# data with special string separators
2019-02-01|||123|||345|||567|||Some unpredictable textual data with pipes|,
2019-02-02|||234|||345|||456|||weird symbols @ and commas, and so on.
2019-02-03|||345|||234|||123|||text text text
EOD
# replace string function
# prefix RS_ to avoid variable name conflicts
replaceStr(s,s1,s2) = (RS_s='', RS_n=1, (sum[RS_i=1:strlen(s)] \
((s[RS_n:RS_n+strlen(s1)-1] eq s1 ? (RS_s=RS_s.s2, RS_n=RS_n+strlen(s1)) : \
(RS_s=RS_s.s[RS_n:RS_n], RS_n=RS_n+1)), 0)), RS_s)
set print $DataOutput
do for [RS_j=1:|$Data|] {
print replaceStr($Data[RS_j],"|||","\t")
}
set print
print $DataOutput
### end of code
哦,哇!我想这是对gnuplot的行家们来说的吧?您已经重新实现了sed's/| | |/\t/g'
。。。只有30行gnuplot代码!那是。。。令人印象深刻的8-)虽然我不认为它遵循unix的原理(我想在这里使用sed
会更惯用),但它令人敬畏,所以(+1)。RSID\u replaceStr
-它是否在s1
长度的所有片段上迭代,从增加RSID\u n
开始,然后将其与s1
进行比较,这大致正确吗?谢谢。我可以将代码简化为约10行;-)。是的,我是“mis”,使用表达式sum[I=1:N](,0)
作为迭代器扫描字符串,并在需要时将s1
替换为s2
。
# data with special string separators
2019-02-01 123 345 567 Some unpredictable textual data with pipes|,
2019-02-02 234 345 456 weird symbols @ and commas, and so on.
2019-02-03 345 234 123 text text text