Moim celem jest spłaszczenie struktury podobnej do systemu plików (zagnieżdżonych katalogów) z informacjami historycznymi dla poszczególnych plików do pliku csv do dalszego przetwarzania. Tutaj jest to, czego próbowałem do tej pory.
Uproszczone dane wejściowe wyglądają następująco:
{ "dirs": [
{
"name": "documents",
"files": [
{
"name": "foo.bar",
"history": [
{ "hash": "123", "timestamp": "..."},
{ "hash": "234", "timestamp": "..."}
]
}
],
"subDirs": [
{ "name": "tmp", "files": [...], "subDirs": [...]
}
]
}
]}
Podstępna część polega na tym, że plik csv powinien zawierać pełne ścieżki katalogów, a nie tylko nazwę katalogu. Żądane wyjście wygląda następująco:
"documents","foo.bar","123","..."
"documents","foo.bar","234","..."
"documents","bar.baz","345","..."
"documents","bar.baz","456","..."
"documents/tmp","deleteme","567","..."
"documents/tmp","deleteme","678","..."
Spłaszczanie większości danych przy użyciu recurse
działa przy użyciu tego zapytania:
.dirs[] | recurse(.subDirs[]?) | . as $d | $d.files[]? as $f | $f.history[]? as $h | [$d.name, $f.name, $h.hash, $h.timestamp] | @csv
... ale nie mogę pojąć, jak mogę zachować ścieżkę do katalogu. Wszelkie sugestie będą mile widziane.
2 odpowiedzi
Myślę, że musisz zdefiniować w tym celu niestandardową funkcję rekurencyjną, jak poniżej; co zakłada, że wszystkie pliki mają niepusty history
.
def f(pfix):
( [ pfix, .name ] | join("/") ) as $path |
( .files[] | .history[] as $hist | [ $path, .name, $hist[] ] ),
( .subDirs[] | f($path) );
.dirs[] | f(empty) | @csv
Oto podejście, które ani nie używa rekurencji jawnie (*), ani nie opiera się na strukturze rekurencyjnej:
def names($path):
reduce getpath($path[0:range(0; $path|length)]) as $v ("";
if $v | type == "object" and has("name") then . + "/" + $v["name"] else . end) ;
paths as $p
| getpath($p) as $v
| select($v | objects | has("history"))
| [names($p), getpath($p + ["name"])]
+ ($v["history"][] | [.hash, .timestamp] )
| @csv
Daje to ścieżki „bezwzględne” (np. „/ Dokumenty”); pominięcie wiodącego „/” może być wykonane dość łatwo.
(*) paths
jest zdefiniowane rekurencyjnie, ale w sposób, który wykorzystuje optymalizację wywołań ogonowych (TCO) jq, która jest stosowana tylko do funkcji rekurencyjnych arity-0.
Podobne pytania
Nowe pytania
json
JSON (JavaScript Object Notation) to serializowalny format wymiany danych przeznaczony do odczytu maszynowego i ludzkiego. Nie używaj tego tagu dla natywnych obiektów JavaScript ani literałów obiektów JavaScript. Zanim zadasz pytanie, sprawdź poprawność JSON za pomocą walidatora JSON, takiego jak JSONLint (https://jsonlint.com).