我有一个输入文件UPDATE entrance SET name="Ritish Karki" WHERE symbol="15369-2017-02"
,其中使用三重分隔符作为分隔符,第一列中的日期,最后一列中的文本或多或少有些不可预测:
example.data
当我尝试运行以下gnuplot5脚本
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
我收到以下错误:
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
,但不适用于其他数字。为什么?
答案 0 :(得分:1)
使用
时1:10
语法,不将字符串视为一个长分隔符。取而代之的是,引号之间列出的每个字符将自己变成分隔符。摘自[Janert,2016]:
如果您提供一个明确的字符串,则字符串中的每个字符将为 视为分隔符。
因此
set datafile separator "chars"
实际上等于
set datafile separator "|||"
和一行
set datafile separator "|"
被视为具有十列,其中只有1,4,7,10列为非空。
解决方法
找到其他不太可能出现在数据集中的字符(在下文中,我以2019-02-05|||123|||456|||789
为例)。如果无法使用其他分隔符转储数据集,请使用\t
将sed
替换为|||
:
\t
然后继续
sed 's/|||/\t/g' example.data > modified.data # in the command line
和set datafile separator "\t"
作为输入。
答案 1 :(得分:1)
您基本上是自己回答的。
如果可以影响数据中的分隔符,请使用通常不会出现在数据或文本中的分隔符。我一直以为\t
是为此而造的。
如果不能影响数据中的分隔符,请使用外部工具(awk,Python,Perl等)来修改数据。在这些语言中,它可能是“单线”。 gnuplot没有直接替换功能。
如果您不想安装外部工具并希望确保平台独立性,仍然可以使用gnuplot做到这一点。不仅是一个“单线”,而且gnuplot ;-)也几乎没有什么不能做的。
编辑:简化版本,其中包含@Ethan(https://stackoverflow.com/a/54541790/7295599)的输入。
假设您的数据位于名为$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
输出:
# 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