Przejrzałem inne odpowiedzi, ale nie mogłem uzyskać odpowiedniego wyjaśnienia, jak to zrobić.
I mieć zmienną łańcuchową o nazwie id
taką, że id="{"name":"john"}"
. Jak mogę uzyskać 2 zmienne z tego ciągu, takie jak-
key="name" value="john"
Szczegółowe wyjaśnienie byłoby mile widziane, ponieważ chcę zrozumieć parsowanie ciągów w bash.
Do tej pory usunąłem nawiasy klamrowe {}
z ciągu-
id="$( echo "${id}" | tr -d {} )"
Nie mogę umieścić w nim "
jako generuje błąd. Poszukuje też czegoś takiego jak id.split(":")
na końcu, aby uzyskać tablicę.
Komentarze
Odpowiedź
Używając jq
:
id="{"name":"john"}" key=$(jq -r keys[] <<<"$id") value=$(jq -r .[] <<<"$id")
-r
: Z tą opcją, jeśli filtr „s wynik jest ciągiem, a następnie zostanie zapisany bezpośrednio na standardowe wyjście, a nie sformatowany jako ciąg JSON w cudzysłowach.
keys
: Wbudowane klawisze funkcyjne, gdy po otrzymaniu obiektu zwraca jego klucze w tablicy.
Używanie json
:
id="{"name":"john"}" key=$(json -ak <<<"$id") value=$(json -a "$key" <<<"$id")
-a
przetwarza dane wejściowe jako tablicę
-k
zwraca wartości kluczy
Komentarze
- Dziękuję za wyjaśnienie. Działa świetnie. Myślę, że ' nie ma możliwości przeanalizowania ciągu bez
jq
w skryptach basha. - @kev: Jest wiele sposobów analizowania ciągów, ale jest to ' trochę niesprawiedliwe aby nazwać to ciągiem znaków, a nie danymi json.
- @kev Dane JSON mogą być kodowane. Aby go przeanalizować, potencjalnie musiałbyś go zdekodować. Ponadto JSON nie dba o białe znaki (znaki nowej linii itp.) Między kluczami i wartościami, więc musisz to wziąć pod uwagę. Zostało to już zrobione przez autorów bazowego parsera JSON w
jq
.
Odpowiedź
Dosłownie prosiłeś o understand string parsing in bash
, więc napiszę odpowiedź, mając to na uwadze, mimo że jest to złe rozwiązanie twojego problemu . Możesz używać samego basha, aby robić, co chcesz, jeśli masz naprawdę czyste dane bez znaków specjalnych, gdzie specjalne jest zdefiniowane jako wszystko spoza [A-Za-z0-9 ]
:
$name":"john"}" $ # remove everything through the first "{" $ echo $id "name":"john"} $ # remove everything starting with the last "}" $ echo $id "name":"john" $ name="${id%:*}" # take everything before the ":" $ name="${name//\"/}" # remove quotes $ echo $name name $ value="${id#*:}" # take everything after the ":" $ value="${value//\"/}" # remove quotes $ echo $value john
Wszystko to jest opisane w „Rozwijaniu parametrów” w podręczniku bash . Na przykład ${parameter#word}
, co spowoduje Remove matching prefix pattern
, usunie tekst word
z początku $parameter
. Podobnie %
usuwa przyrostek. //
zamienia wszystkie wystąpienia ciągu na wszystko, co nastąpi po nim (w przykładzie ${foo//\"/}
powyżej, cudzysłowy (które muszą zostać zmienione, więc pojawiają się jako \"
) są zastępowane pustym ciągiem znaków). Musisz jednak wykonać każde podstawienie samodzielnie: nie możesz odciąć początku i końca łańcucha jednym poleceniem.
Prawdopodobnie zauważyłeś również, że trzeba zmienić znaczenie znaków specjalnych, takich jak }
, {
i "
. Tak długo, jak pamiętasz, aby zrobić to dobrze, możesz napisać taki kod z łatwością, ale mimo tego, że jest on prosty, ma on tendencję do bycia kodem tylko do zapisu. za rok lub dwa, aby ponownie go użyć, spojrzysz na coś takiego jak #*\{}
i pomyślisz sobie: WTF czy to w ogóle oznacza? i następnie skopiuj go na ślepo do nowego projektu, a kod ulegnie subtelnemu zepsuciu, ponieważ napotka znaki specjalne, których się nie spodziewałeś.
Powyższe przykłady nie powiodą się, jeśli pary nazwa-wartość zawierają znaki specjalne, takie jak nawiasy klamrowe, cudzysłowy, dwukropki lub prawdopodobnie inne znaki. Więc to zadziała dobrze w przypadku szybkiego i brudnego skrobania lub przypadku użycia 80%, ale naprawdę nie powinieneś używać go w produkcji ani za każdym razem, gdy musisz upewnić się, że zawsze działa z jakimkolwiek wejściem.
Nawet bez instrukcji echo
, które pokazują, co się dzieje, możesz zobaczyć, że ten kod jest już dłuższy niż przykłady w innej odpowiedzi, które pokazują, jak to zrobić prawidłowo. Dlatego nie korzystając z narzędzia innej firmy, „dajesz sobie więcej kodu do napisania, co zajmie więcej czasu zarówno na pisanie, jak i debugowanie”. Otrzymujesz również rozwiązanie, które jest mniej elastyczne i przerywa, gdy napotyka coś nieoczekiwanego.
Komentarze
- to było dość pouczające – czy ' t nie rozumieć, dlaczego ludzie mieliby głosować przeciw
Odpowiedz
Alternatywnie możesz użyć uniksa opartego na ścieżce narzędzie jtc
:
id="{"name":"john"}" bash $ key=$(jtc -w"[0]<>k" <<<"$id") bash $ echo $key "name" bash $ value=$(jtc -w"[0]" <<<"$id") bash $ echo $value "john" bash $
PS> Ujawnienie: Jestem twórcą narzędzia jtc
– powłoki CLI do operacji JSON
jq
jest używane przez innych, ale czy nie ma możliwości, żebym mógł to przeanalizować bez osoby trzeciej narzędzie?awk
,sed
igrep
to również narzędzia innych firm. Jeśli używasz danychjson
, nie ma absolutnie żadnego powodu, aby nie mieć odpowiednich narzędzi do pracy z nimi.