У меня есть куча файлов .tcx (по сути, это файл XML, выведенный устройством GPS) в папке. Они следуют соглашению об именовании DATE_LOCATION_SPORT.tcx. Каждый файл содержит кучу узлов точек трека, отмечающих ключевые данные GPS, записанные каждую секунду, в которых есть дочерний узел расстояния до сих пор под названием «DistanceMeters». Я хочу выполнить grep по каждому файлу и найти последний узел «DistanceMeters», а затем вывести этот список расстояний. Вот фрагмент из файла. (Я использую терминал OS X Sierra)
…
<Trackpoint>
<Time>2017-04-09T08:15:29.000Z</Time>
<Position>
<LatitudeDegrees>0.123456</LatitudeDegrees>
<LongitudeDegrees>-0.654321</LongitudeDegrees>
</Position>
<AltitudeMeters>24.363636363636363</AltitudeMeters>
<DistanceMeters>1382.3235298511217</DistanceMeters>
<HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>130</Value>
</HeartRateBpm>
</Trackpoint>
…
Я начал с попытки сделать это всего с одним файлом (обратите внимание, в именах некоторых файлов есть пробелы, не уверен, что это меня сбивает с толку);
grep '<DistanceMeters>.*<\/DistanceMeters>' '2017-03-23_Somewhere_Running.tcx' | tail -1 | grep -o '[0-9]\+\.[0-9]\+'
Который очень удачно получает последний узел «DistanceMeters», а затем использует grep для извлечения числового расстояния, а не всей строки XML.
find . -iname '2017*_Running.tcx'
Выше приведен список всех файлов, которые меня интересуют в этом году.
Но когда я пытаюсь объединить команды, все разваливается. Я получаю либо ошибку о том, что не заканчивается на "\;", либо получаю ответ, но только последнее значение расстояния для последнего файла в списке файлов, а не расстояние для каждого.
Итак, это дает мне окончательное расстояние до последнего файла в списке;
find . -iname '*_Running.tcx' -print0 | xargs -0 grep '<DistanceMeters>.*<\/DistanceMeters>' | tail -1 | grep -o '[0-9]\+\.[0-9]\+'
Как и это;
find . -iname '*_Running.tcx' -exec grep '<DistanceMeters>.*<\/DistanceMeters>' {} \; | tail -1 | grep -o '[0-9]\+\.[0-9]\+'
Я пробовал разные комбинации, но не уверен, как их объединить так, как мне нужно. Я думал, что, может быть, поставив "\;" в конце, это сработает, но это не работает - жалуется, что не заканчивается на ";" или "+".
find . -iname '*_Running.tcx' -exec grep '<DistanceMeters>.*<\/DistanceMeters>' {} | tail -1 | grep -o '[0-9]\+\.[0-9]\+' \;
урожайность
grep: ;: No such file or directory
find: -exec: no terminating ";" or "+"
Есть идеи?
Спасибо, что дочитали до этого места!
решение1
Проблема здесь в кавычках... Я не знаю, есть ли способ правильно заключить это в кавычки, чтобы опция «exec» для find(1) принимала конвейер команд.
Вот один из способов обойти эту проблему:
$ for rfile in $(find . -iname '2017*_Running.tcx'); do grep '<DistanceMeters>.*<\/DistanceMeters>' $rfile | tail -1 | grep -o '[0-9]\+\.[0-9]\+'; done