2014-04-04 6 views
8

Czytam plik plist, używając plistbuddy; i zbieram dane z różnych słowników.plistbuddy - Jak przechwytywać błędy (klucz nie istnieje)

Problem polega na tym, że czasami nie ma tam wartości, z tego czy innego powodu, więc otrzymuję wynik "Key does not exist".

Czy istnieje sposób na przechwycenie tego, więc jeśli wartość nie istnieje, mogę zastąpić ją wartością 0 lub inną?

Używam skryptu powłoki; Myślałem, aby użyć prostego oświadczenia if ... else, próbowałem sprawdzić ciąg "key does not exist", ale to nie działa (nigdy nie uderzyłem w warunek true, zakładam, że wiadomość jest po prostu zamiana na stdout, zamiast być zapisany w mojej zmiennej) .

Dokumentacja nie pomogła, więc utknąłem.

Ponieważ obliczam średnią, błąd powoduje, że moje obliczenia są męczące i dlatego chcę dodać 0, więc mogę sprawdzić później, czy jest 0 i zmienić funkcję, aby odpowiednio obliczyć średnią.

Zasadniczo jest to przykład z mojego kodu: (filename to nazwa pliku plist)

for i in {0..3} 
do 
    TempValue=$(/usr/libexec/PlistBuddy -c "print :process:$i:testname:result" $fileName) 
    echo $TempValue 
    Data_results+=($TempValue) 
done 

# Calculate Average 
tmpResult=`echo ${Data_results[0]} + ${Data_results[1]} + ${Data_results[2]} + ${Data_results[3]}|bc` 
AverageTime=$(bc <<< "scale=10; $tmpResult/4") 
echo "average for test name: " $AverageValue 

Dzięki! /usr/libexec/PlistBuddy narzędzie

Odpowiedz

10

OS X jest dobrze ułożona CLI:

  • w przypadku powodzenia, jego kod wyjścia jest 0
  • w przypadku awarii, jego kod wyjścia jest niezerowy
  • jego regularne wyjścia jest wysyłany do stdout, komunikaty o błędach są wysyłane do stderr

Istnieją różne sposoby sprawdzania, czy nie ma sukcesu; np .:

# Query and save the value; suppress any error message, if key not found. 
val=$(/usr/libexec/PlistBuddy -c 'print ":SomeKey"' file 2>/dev/null) 

# Save the exit code, which indicates success v. failure 
exitCode=$? 

if ((exitCode == 0)) then # OK 
    # handle success .... 
else 
    # handle failure ... 
fi 

Aktualizacja 1

Oto urywek Twoim przypadku konkretnego zastosowania; można go uruchomić jak jest, aby zobaczyć jak to działa (używa pliku PLIST w którym Finder przechowuje preferencje):

# Loop over keys and retrieve the corresponding values. 
# If the key doesn't exist, assign '0'. 
for key in ':AppleShowAllFiles' ':NoSuchKey'; do 
    val=$(/usr/libexec/PlistBuddy -c "print \"$key\"" \ 
      ~/Library/Preferences/com.apple.finder.plist 2>/dev/null || printf '0') 
    echo "Value retrieved: [$val]" 
done 

Jak zobaczysz, $val będzie zawierał 0 w przypadku 2, nieistniejący klucz.

2>/dev/null hamuje stderr (wiadomości o błędzie) i operator || służy do zapewnienia alternatywnej polecenia utworzenia wyjściowe w przypadku, gdy wywołanie PlistBuddy sygnalizuje awarię (poprzez kod zakończenia).

Jedynym zastrzeżeniem jest to, że nie można odróżnić nieistniejącego klucza od bardziej fundamentalnej awarii, takiej jak nieistniejący lub uszkodzony plik Plist.Obsługa, która byłaby bardziej zaangażowana, ponieważ PlistBuddy nie używa różnych kodów wyjścia w celu rozróżnienia tych przypadków.


Aktualizacja 2

Oto usprawnione wersja kodu, który zawiera pożądany logikę default-do-0: Tylko $((...)) jest wyrażeń arytmetycznych (liczby całkowite:

# Collect temperatures. 
Data_results=() 
for i in {0..3} 
do 
    Data_results+=($(/usr/libexec/PlistBuddy \ 
      -c "print :process:$i:testname:result" "$fileName" 2>/dev/null || 
      printf '0')) 
done 

# Calculate average 
AverageValue=$(bc <<< \ 
       "scale=10; $((${Data_results[@]/%/ +} 0))/${#Data_results[@]}") 
echo "average for test name: " $AverageValue 

Note), który używa małej sztuczki do podsumowania elementów tablicy: ${Data_results[@]/%/ +} dołącza + do każdego elementu tablicy. Np. Tablica wejściowa o numerze (1 2 3) może rozwinąć się do 1 + 2 + 3 +; ponieważ pozostawia zwisające +, po prostu dodałem kolejne 0, aby utworzyć prawidłowe wyrażenie. W połączeniu z dzieleniem przez ${#Data_results[@]} - liczba elementów w tablicy - polecenie działa następnie z tablicą o dowolnym rozmiarze.

+0

Dzięki za odpowiedź. Mam świadomość, że zwraca błąd, gdy się nie powiedzie, ale nie będzie się zachowywać tak, jak się spodziewam. Mam gdzie, jeśli w pętli piszę plist, zbieram 4 wartości; jeśli jednej z wartości nie ma, nie kończę pracy ... skrypt jest kontynuowany. Nie mogę użyć kodu wyjścia, ponieważ nie wykonuję tego narzędzia tylko raz, ale jest to część bardziej złożonego skryptu powłoki. –

+1

@newbiez: Myślę, że masz błędne przekonanie na temat kodów wyjścia: każde wywołanie polecenia w skrypcie ustawia kod wyjścia, wskazując, że to polecenie zakończyło się powodzeniem lub porażką. Możesz uzyskać bezpośredni dostęp do tego kodu wyjścia za pomocą '$?' Lub możesz użyć instrukcji 'if', a operatory' && 'i' || 'działają na sukcesie lub niepowodzeniu. Zapoznaj się z moją zaktualizowaną odpowiedzią dotyczącą fragmentu, który - mam nadzieję - spełnia Twoje oczekiwania. – mklement0

+0

Rzeczywiście nie byłem tego świadomy; Po prostu myślałem, że kod wyjścia jest albo wywoływany przez ciebie gdzieś w skrypcie, z "wyjściem", albo gdy skrypt osiąga koniec. Dziękuję za wyjaśnienie! –