Вообще, исходная задача — написать
XLS2
KML-конвертер.
XLS парсить не очень удобно, поэтому задачу можно привести к виду
CSV2KML.
Тем более, что XLS делается хз-кем и хз-как, не исключено, что вообще руками набивается.
Короче-говоря, можно считать, что набор входных данных формализован весьма относительно.
Так что есть вероятность необходимости внесения правок в скрипт для каждого входного файла.
Поэтому предпочтение отдаётся интерпретируемым языкам.
Пока получается так:
#!/bin/bash
# Coded by: ArcFi <arcfi[dot]x[at]gmail[dot]com>
# License: GNU General Public License (GPL) version 3+
dms2dd() {
DMS="$*"
DEG=$(awk --field-separator='[^0-9.]*' '{print $1}' <<< "$DMS")
MIN=$(awk --field-separator='[^0-9.]*' '{print $2}' <<< "$DMS")
SEC=$(awk --field-separator='[^0-9.]*' '{print $3}' <<< "$DMS")
DD=$(bc <<< "scale=8;$DEG+$MIN/60+$SEC/3600")
echo "$DD"
}
FILE_NAME="${1:?}"
CSV_SEP="${2:-|}"
exec >"${FILE_NAME%%.csv}.kml"
echo -e '<?xml version="1.0" encoding="UTF-8"?>\n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>'
sed 's/\x0d$//' "$FILE_NAME" | while read LINE
do
LABEL_NAME=$(awk --field-separator="$CSV_SEP" '{print $1}' <<< "$LINE")
LATITUDE_DMS=$(awk --field-separator="$CSV_SEP" '{print $2}' <<< "$LINE")
LONGTITUDE_DMS=$(awk --field-separator="$CSV_SEP" '{print $3}' <<< "$LINE")
LATITUDE=$(dms2dd "$LATITUDE_DMS")
LONGTITUDE=$(dms2dd "$LONGTITUDE_DMS")
ALTITUDE="0"
echo -e "<Placemark>\n\t<name>$LABEL_NAME</name>\n\t<Point>\n\t\t<coordinates>$LONGTITUDE,$LATITUDE,$ALTITUDE</coordinates>\n\t</Point>\n</Placemark>"
done
echo -e '</Document>\n</kml>'
exit 0
951|65°36'38.1"|33°12'04.0"
952|65°37'04.2"|33°11'23.1"
мост 952+665м|65°37'22.2"|33°10'50.4"
953|65°37'31.3"|33°10'35.8"
954|65°38'03.2"|33°10'17.8"
...
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<Placemark>
<name>951</name>
<Point>
<coordinates>33.20111111,65.61058333,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>952</name>
<Point>
<coordinates>33.18974999,65.61783332,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>мост 952+665м</name>
<Point>
<coordinates>33.18066666,65.62283332,0</coordinates>
</Point>
</Placemark>
<Placemark>
<name>953</name>
<Point>
<coordinates>33.17661110,65.62536110,0</coordinates>
</Point>
</Placemark>
...
</Document>
</kml>
***
Axa-Ru, за ссылки спасибо, куда копать, понял.
***
Заменил 3 вызова awk на 1 sed:
dms2dd() {
read DEG MIN SEC <<< $(sed 's/[^0-9\.]\{1,\}/ /g' <<< "$*")
echo $(bc <<< "scale=8;$DEG+$MIN/60+$SEC/3600")
}
***
Вовсе избавился от awk:
IFS="$CSV_SEP" read LABEL_NAME LATITUDE_DMS LONGTITUDE_DMS <<< "$LINE"
***
Можно считать, что решено.
Такой вариант меня устраивает:
#!/bin/bash
# Coded by: ArcFi <arcfi[dot]x[at]gmail[dot]com>
# License: GNU General Public License (GPL) version 3+
# CSV2KML-converter
# Degrees, Minutes, Seconds to Decimal Degrees
dms2dd() {
read DEG MIN SEC <<< $(sed 's/[^0-9\.]\{1,\}/ /g' <<< "$*")
echo $(bc <<< "scale=8;$DEG+$MIN/60+$SEC/3600")
}
FILE_NAME="${1:?}"
CSV_SEP="${2:-|}"
exec >"${FILE_NAME%%.csv}.kml"
echo -e '<?xml version="1.0" encoding="UTF-8"?>\n<kml xmlns="http://www.opengis.net/kml/2.2">\n<Document>'
sed 's/\x0d$//' "$FILE_NAME" | while read LINE
do
IFS="$CSV_SEP" read LABEL_NAME LATITUDE_DMS LONGTITUDE_DMS <<< "$LINE"
LATITUDE=$(dms2dd "$LATITUDE_DMS")
LONGTITUDE=$(dms2dd "$LONGTITUDE_DMS")
ALTITUDE="0"
echo -e "<Placemark>\n\t<name>$LABEL_NAME</name>\n\t<Point>\n\t\t<coordinates>$LONGTITUDE,$LATITUDE,$ALTITUDE</coordinates>\n\t</Point>\n</Placemark>"
done
echo -e '</Document>\n</kml>'
exit 0