BASH 从多个 csv 文件中提取带条件的数据,对数据进行排序并删除双精度。需要加快进程

问题描述 投票:0回答:2

我有一个业余网站,为骑自行车的人提供赛道。

该网站的目标之一是沿着 gpx 轨道提供 POI(兴趣点)。

我有数百个数据库,每个数据库都有数千条数据。

目前,我创建了一个脚本,用于搜索距特定 gpx 点 1 公里范围内的 POI,将结果添加到文件中,对它们进行排序,删除双打。

它可以工作,但由于我计划将每个轨道添加到我的网站,因此我需要重复该过程 5K 次,这导致操作非常慢。

这是我安排的代码

#!/bin/sh

POI_FILES="poi_files.list"

find Db_Poi_Base/ -type f >"${POI_FILES}"

awk -F,   '$1>12.295 \
    && $1<12.579 \
    && $2>46.186 \
    && $2<46.289 {
        print $0 ",",FILENAME
    }' "${POI_FILES}" > "poi_base.txt"

# Looping from this point to end of script
awk -F,   '$1>13.136357 \
    && $1<13.156357 \
    && $2>45.679686 \
    && $2<45.699686 {
        print $0 ",",FILENAME
    }' "${POI_FILES}" > "poi_base1.txt"

if [ -s "poi_base.txt" && -s "poi_base1.txt" ]
then
    cat poi_base.txt poi_base1.txt |
        awk '!seen[$0]++' > poi_base2.txt
fi

if [ -s "poi_base2.txt" ]
then
    sed 's/\r//' poi_base2.txt > poi_base.txt
fi

首先AWK在识别的文件内部进行搜索,将结果与特定参数相匹配,然后添加逗号和特定数据库的文件名,在其中找到数据;最后将所有内容保存到txt文件中。

第二个 AWK 执行与第一个 AWK 相同的操作,只是 txt 文件名发生了更改。

之后,两个数据文件将被合并并传递给 AWK 以删除双打并创建第三个文件。

最后,将检查数据以删除可能存在于同一行中的^M字符(回车符),将结果文件命名为与第一行相同;这让我只用 3 个文件循环。

从第二个 AWK 开始,将循环更改参数,直到分析点结束。

原始 gpx 文件具有以下结构

Index   Lat         Lon     
0   45.689686   N   45° 41.381160' N    13.146357   E   13° 8.781420' E
1   45.689657   N   45° 41.379420' N    13.146311   E   13° 8.778660' E

Poi 的 Dbase 文件具有以下结构(用逗号分隔的三列 csv 文件)

9.107150,39.219720,Moto Race Srl Accessori Abbigliament Cagliari>39070651423
9.141090,39.236280,Il Centauro Dei Fratelli Sanna Cocco Cagliari>39070492692
9.176310,39.241830,Planet Motors Aprilia Conce Quartu Sant'elena>39070881179

在生成脚本时,我将在开源电子表格上导入数据并使用一些公式对其进行管理。 例如,将+0.01和-0,01值(1公里)输入Lat和Lon,以获得搜索范围...

由于一切正常,即使速度慢得令人难以置信,我想知道是否有办法加快进程。 我也尝试过使用数组,如下所示

IFS=$'\n'&&i=5491&&readarray -t my_array1 < <(find Db_Poi_Base/ -type f -exec awk -F, '$1>13.136357 && $1<13.156357 && $2>45.679686 && $2<45.699686 {print $0 ",",FILENAME}' {} \;)&&echo durata stimata: 91,5 minuti&&echo riga: $i ;((i=i-1))

readarray -t my_array2 < <(find Db_Poi_Base/ -type f -exec awk -F, '$1>12.946311 && $1<13.346311 && $2>45.489657 && $2<45.889657 {print $0 ",",FILENAME}' {} \;)&& my_array1+=(${my_array2[@]})&&echo riga: $i ;((i=i-1))

第一行部分(IFS=$' '&&i=5491&&) 用于避免回车并设置倒计时变量以表明脚本正在进行中。 每行的第二部分 (&&echo riga: $i ;((i=i-1)) 在回显行号后减少变量。

数组解决方案仅部分有效,因为它没有排序和删除双精度数。

预期输出如下

13.143540,45.688900,UD Lignano Sabbiadoro -(H R) Desiree>39043171415, Db_Poi_Base/Ristoranti_Senza_Glutine/Ristoranti_Senza_Glutine.csv
13.140550,45.688220,T La Conchiglia Lignano Sabbiadoro UD>39043173861, Db_Poi_Base/Tabacchi/Tabacchi.csv
13.142680,45.689260,T Sebastianis Laura Lignano Sabbiadoro UD>390431720656, Db_Poi_Base/Tabacchi/Tabacchi.csv
13.144810,45.691160,T Di Bella Salvatore Lignano Sabbiadoro UD>39043173820, Db_Poi_Base/Tabacchi/Tabacchi.csv
13.143750,45.691250,T Gusso Luigi Lignano Sabbiadoro UD>39043170187, Db_Poi_Base/Tabacchi/Tabacchi.csv
13.146660,45.691940,T Zamolo Metullio Lignano Sabbiadoro UD>39043170777, Db_Poi_Base/Tabacchi/Tabacchi.csv
13.148370,45.693080,T Passilongo Mario Lignano Sabbiadoro UD>39043171922, Db_Poi_Base/Tabacchi/Tabacchi.csv

这些是我的首要问题。

作为次要的好奇心,但实际上并不是一个很好的好奇心,就像电子表格一样,一切都足够快,就是直接在脚本中实现 gpx 文件,例如使用 do while 循环,从外部 gpx 文件读取每一行,并将亲属列的数据放入命令序列中。

感谢您的任何建议。

bash csv sorting awk double-submit-problem
2个回答
0
投票

由于两个文件的格式相同,您可以通过简单地执行以下操作来删除重复项:

cat poi_base.txt poi_base1.txt | sort | uniq |

对于项目的总体概念,我建议为每个兴趣点(POI)分配一个唯一的ID,如下所示:

poi_00903|9.107150,39.219720,Moto Race Srl Accessori Abbigliament Cagliari>39070651423
poi_00904|9.141090,39.236280,Il Centauro Dei Fratelli Sanna Cocco Cagliari>39070492692
poi_00905|9.176310,39.241830,Planet Motors Aprilia Conce Quartu Sant'elena>39070881179

该 ID 可能与自行车/步行道的 ID 相关,也可能无关。

执行一项大型任务,识别每个路径坐标检查点指定范围内 POI 的 ID,并将这些任务在修改后的 GPX 文件 (*.gpx_poi) 中的每个项目行的附加字段中作为附加项目列出。

例如,如果原始 GPX 文件名为

Montessori_053.gpx

一条位置线是

37   45.689657   N   45° 41.379420' N    13.146311   E   13° 8.778660' E

您可以给相关的 POI 文件命名

Montessori_053.gpx_poi

相关行可以格式化(带坐标)为

37   45.689657   N   45° 41.379420' N    13.146311   E   13° 8.778660' E ,poi_00903 poi_00904 poi__00907,poi_00792 poi_00795,poi_0348 poi_01009 poi_01201

或没有坐标

37,poi_00903 poi_00904 poi__00907,poi_00792 poi_00795,poi_0348 poi_01009 poi_01201 

其中第 1、2、3 组分别是 1 公里、3 公里和 10 公里范围内的 POI。

拥有 POI“预分析”和预编译将使应用程序的响应速度更快,因为您已将查找工作量减少到简单的路径索引匹配以获取相关“POI ID”的位置需要提取并显示。

您可能还想创建一个“行程规划器”,在其中提供对沿给定路径识别的所有 POI 的唯一引用,以及复选框。然后,用户可以保存该原始+检查列表以供以后参考。 当用户为他们的旅行选择“开始徒步旅行”时,它会在这些路线上最近的点突出显示“选中的”POI,并带有“pin flag label”。 如果用户改变了他们可能想要访问的内容或访问时间,您可能需要提供“重新访问”原始列表的选项来更改复选标记选择。 只是一些想法。 你的主意非常好。 祝您的项目顺利!


0
投票

首先,我使用以下命令创建一个文件来减少总数据,仅提取特定范围内的数据(最大和最小纬度和经度)。

find Db_Poi_Base/ -type f -exec awk -F, '$1>13.011409 && $1<13.783151 && $2>45.641559 && $2<46.10597 {print $0 ",",FILENAME}' {} > "poi_base-test.txt" \;

比我更改了上面使用的命令的第一部分,设置为在特定文件内搜索:

find poi_base-test.txt -type f -exec awk -F, '$1>13.136357 && $1<13.156357 && $2>45.679686 && $2<45.699686 {print $0}' {} > "poi_base.txt" \;&&i=5491&&echo Termina tra: $t minuti&&echo riga: $i ;((i=i-1));((t=i/45))

结果是正确的,现在已经足够快满足我的需求了

© www.soinside.com 2019 - 2024. All rights reserved.