2014-04-04 17 views
8

Tôi đang đọc một tệp plist, sử dụng plistbuddy; và tôi thu thập dữ liệu từ các từ điển khác nhau.plistbuddy - Cách chặn các lỗi (Khóa không tồn tại)

Vấn đề là đôi khi các giá trị không có, vì một lý do này hoặc lý do khác, vì vậy tôi nhận được như đầu ra "Key does not exist".

Có cách nào để ngăn chặn điều này, để nếu giá trị không tồn tại, tôi có thể thay thế giá trị bằng 0 hoặc giá trị khác không?

Tôi sử dụng tập lệnh shell; Tôi đã suy nghĩ sử dụng câu lệnh if ... else đơn giản, cố gắng kiểm tra chuỗi "key does not exist" nhưng không hoạt động (Tôi chưa bao giờ đạt đến điều kiện true, tôi cho rằng thông báo sẽ chỉ xuất hiện, thay vì được lưu trong biến của tôi) .

Tài liệu không hữu ích nhiều, vì vậy tôi gặp khó khăn.

Vì tôi tính trung bình, lỗi sẽ làm sai lệch tính toán của tôi và đó là lý do tôi muốn thêm 0, vì vậy tôi có thể kiểm tra sau nếu có 0 và thay đổi hàm để tính trung bình cho phù hợp.

Về cơ bản đây là một ví dụ về mã của tôi: (filename là tên tập tin 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 

Cảm ơn! tiện ích /usr/libexec/PlistBuddy

Trả lời

10

OS X là một CLI well-behaved:

  • trong trường hợp thành công, mã thoát của nó là 0
  • trong trường hợp thất bại, mã thoát của nó là khác không
  • đầu ra thường xuyên của nó được gửi đến stdout, thông báo lỗi được gửi đến stderr

Có nhiều cách khác nhau để kiểm tra thành công; ví dụ .:

# 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 

Cập nhật 1

Dưới đây là một đoạn đối với trường hợp sử dụng cụ thể của bạn; bạn có thể chạy nó như-là để xem làm thế nào nó hoạt động (nó sử dụng file Plist trong đó Finder cửa hàng sở thích của nó):

# 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 

Như bạn sẽ thấy, $val sẽ chứa 0 trong trường hợp thứ 2, khóa không tồn tại.

2>/dev/null ngăn chặn đầu ra stderr (thông báo lỗi) và toán tử || được sử dụng để cung cấp lệnh thay thế để tạo đầu ra trong trường hợp lệnh gọi PlistBuddy cho biết lỗi (thông qua mã thoát).

Thông báo trước duy nhất là bạn sẽ không thể phân biệt khóa không tồn tại khỏi lỗi cơ bản hơn, chẳng hạn như tệp Plist không tồn tại hoặc bị hỏng.Việc xử lý có liên quan nhiều hơn, bởi vì PlistBuddy không sử dụng các mã thoát riêng biệt để phân biệt các trường hợp này.


Cập nhật 2

Dưới đây là một phiên bản tinh gọn của mã của bạn bao gồm các mong muốn mặc định-to-0 logic:

# 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 

Lưu ý: $((...)) là một mở rộng số học (số nguyên chỉ) sử dụng một mẹo nhỏ để tổng hợp các phần tử của mảng: ${Data_results[@]/%/ +} gắn thêm + vào mỗi phần tử của mảng. Ví dụ: mảng đầu vào của (1 2 3) sẽ mở rộng thành 1 + 2 + 3 +; kể từ khi rời khỏi một dangling +, tôi chỉ cần thêm một 0 để tạo thành một biểu thức hợp lệ. Kết hợp với chia cho ${#Data_results[@]} - số phần tử trong mảng - lệnh sau đó hoạt động với một mảng có kích thước bất kỳ.

+0

Cảm ơn bạn đã trả lời. Tôi biết rằng nó trả về một mã lỗi khi thất bại, nhưng nó sẽ không hoạt động như tôi mong đợi. Tôi có một nơi mà tôi vòng máng một plist, tôi thu thập 4 giá trị; nếu một trong các giá trị không có, tôi không chỉ đơn giản là thoát ... kịch bản tiếp tục. Vì vậy, tôi không thể sử dụng mã thoát, do thực tế là tôi không thực hiện tiện ích một lần, nhưng nó là một phần của một kịch bản shell phức tạp hơn. –

+1

@newbiez: Tôi nghĩ bạn có quan niệm sai về mã thoát: mọi lệnh gọi một lệnh bên trong tập lệnh đều đặt mã thoát, cho biết lệnh đó đã thoát ra sao về thành công so với thất bại. Bạn có thể truy cập mã thoát này một cách rõ ràng bằng '$?', Hoặc bạn có thể sử dụng các câu lệnh 'if' và' && 'và' || 'để hành động thành công hoặc thất bại. Xin vui lòng xem câu trả lời cập nhật của tôi cho một đoạn mà hy vọng những gì bạn muốn. – mklement0

+0

Thật vậy, tôi đã không nhận thức được điều đó; Tôi chỉ đơn giản nghĩ rằng mã thoát được gọi bởi bạn ở đâu đó trong tập lệnh, với "thoát" hoặc khi tập lệnh kết thúc. Cảm ơn bạn đã làm rõ! –

Các vấn đề liên quan