मैं बश पाइप में कच्चे बाइनरी डेटा को कैसे संभाल सकता हूं?


15

मेरे पास एक बैश फ़ंक्शन है जो एक फ़ाइल को पैरामीटर के रूप में लेता है, यह सत्यापित करता है कि फ़ाइल मौजूद है, फिर फ़ाइल के लिए स्टिंग आ रहा कुछ भी लिखता है। भोला समाधान पाठ के लिए ठीक काम करता है, लेकिन मुझे मनमाने ढंग से द्विआधारी डेटा के साथ समस्या हो रही है।

echo -n '' >| "$file" #Truncate the file
while read lines
do  # Is there a better way to do this? I would like one...
    echo $lines >> "$file"
done

जवाबों:


15

आपका रास्ता हर उस चीज़ में लाइन ब्रेक जोड़ रहा है जो इसे अलग करने वाले के स्थान पर लिखता है ( $IFS) रीड को विभाजित करने के लिए उपयोग कर रहा है। इसे तोड़ने के बजाय इसे पूरी तरह से ले लें और इसे पास करें। आप इसके ऊपर दिए गए पूरे कोड को कम कर सकते हैं:

 cat - > $file

आपको ट्रंकट बिट की आवश्यकता नहीं है, यह पूरी तरह से छोटा हो जाएगा और इसे पूरा STDIN स्ट्रीम लिख देगा।

संपादित करें: यदि आप zsh का उपयोग कर रहे हैं तो आप > $fileबिल्ली के स्थान पर उपयोग कर सकते हैं । आप किसी फ़ाइल पर रीडायरेक्ट कर रहे हैं और उसे छोटा कर रहे हैं, लेकिन अगर वहाँ कुछ भी लटका हुआ है तो STDIN को स्वीकार करने के लिए किसी चीज़ का इंतज़ार करना होगा, यह उस बिंदु पर पढ़ने को मिलेगा। मुझे लगता है कि आप बैश के साथ ऐसा कुछ कर सकते हैं लेकिन आपको कुछ विशेष मोड सेट करने होंगे।


मुझे काम करने के लिए स्टड पुनर्निर्देशित उदाहरण नहीं मिला, लेकिन बिल्ली उदाहरण को बदलकर> | (मेरे पास noclobber सेट है) एक आकर्षण की तरह काम करता है। मेरा दिन बनाने के लिए धन्यवाद ^। ^
डेविड सोथर

बिल्ली-कम संस्करण के लिए +1। हमेशा बेकार बिल्लियों से बचें;)
rozcietrzewiacz

@rozcietrzewiacz: सच है, सिवाय इसके कि यह एक झगड़ा था और मैं गलत था। यह बिल्ली का बेकार उपयोग नहीं हो सकता है। केवल एक चीज जो आप कर सकते हैं वह है > $file। यह केवल पहली चीज के रूप में काम करता है जो मूल शैल स्क्रिप्ट में स्टडिन के लिए दिखता है। मूल रूप से डेविड के सभी कोड को एक एकल चरित्र में कम किया जा सकता है, लेकिन मुझे लगता है कि cat -यह अधिक सुरुचिपूर्ण और कम परेशानी वाला है क्योंकि यह दृष्टि पर समझा जाता है।
कैलेब

कभी कभी मैं स्ट्रिंग चार या पांच catरों एक साथ, बस परेशान UUOC कट्टरपंथियों को
माइकल Mrozek

@MichaelMrozek: कभी-कभी मैं अपनी डेटा फ़ाइलों को catसिर्फ इसलिए नाम देता हूं कि जो लोग इसे इस्तेमाल करने के लिए जोर देते हैं, उन्हें कोड पढ़ने के लिए मानसिक जिम्नास्टिक करना पड़ता है। नामांकित पाइप भी अच्छे लक्ष्य हैं।
कालेब

7

पाठ फ़ाइल को शाब्दिक रूप से पढ़ने के लिए, सादे का उपयोग न करें read, जो आउटपुट को दो तरीकों से संसाधित करता है:

  • read\पलायन चरित्र के रूप में व्याख्या ; read -rइसे बंद करने के लिए उपयोग करें।
  • readपात्रों में शब्दों में विभाजित $IFS; IFSइसे बंद करने के लिए एक खाली स्ट्रिंग पर सेट करें।

लाइन द्वारा एक पाठ फ़ाइल लाइन को संसाधित करने के लिए सामान्य मुहावरा है

while IFS= read -r line; do 

इस मुहावरे की व्याख्या के लिए, देखें कि while IFS= readइसके बजाय अक्सर ऐसा क्यों किया जाता है IFS=; while read..?

एक स्ट्रिंग को शाब्दिक रूप से लिखने के लिए, केवल सादे का उपयोग न करें echo, जो स्ट्रिंग को दो तरीकों से संसाधित करता है:

  • कुछ गोले पर, echoबैकलैश से बच निकलता है। (बैश पर, यह निर्भर करता है कि xpg_echoविकल्प सेट है या नहीं।)
  • कुछ तारों को विकल्पों के रूप में माना जाता है, जैसे ( -nया -eसटीक सेट शेल पर निर्भर करता है)।

शाब्दिक रूप से एक स्ट्रिंग को मुद्रित करने का एक पोर्टेबल तरीका है printf। (बैश में कोई बेहतर तरीका नहीं है, जब तक आप जानते हैं कि आपका इनपुट विकल्प की तरह नहीं दिखता है echo।) सटीक स्ट्रिंग को प्रिंट करने के लिए पहले फ़ॉर्म का उपयोग करें, और दूसरा रूप यदि आप एक नई पंक्ति जोड़ना चाहते हैं।

printf %s "$line"
printf '%s\n' "$line"

यह केवल प्रोसेसिंग टेक्स्ट के लिए उपयुक्त है , क्योंकि:

  • अधिकांश गोले इनपुट में अशक्त पात्रों पर चोक करेंगे।
  • जब आपने अंतिम पंक्ति पढ़ी है, तो आपके पास यह जानने का कोई तरीका नहीं है कि अंत में एक नई रेखा थी या नहीं। (कुछ पुराने गोले बड़ी मुसीबत हो सकते हैं यदि इनपुट एक नई रेखा के साथ समाप्त नहीं होता है।)

आप शेल में बाइनरी डेटा को संसाधित नहीं कर सकते हैं, लेकिन अधिकांश यूनियनों पर उपयोगिताओं के आधुनिक संस्करण मनमाने डेटा के साथ सामना कर सकते हैं। आउटपुट के माध्यम से सभी इनपुट पास करने के लिए, उपयोग करें cat। स्पर्शरेखा पर जाना, echo -n ''कुछ न करने का एक जटिल और गैर-पोर्टेबल तरीका है; echo -nसिर्फ उतना ही अच्छा होगा (या शेल के आधार पर नहीं), और :सरल और पूरी तरह से पोर्टेबल है।

: >| "$file"
cat >>"$file"

या, सरल,

cat >|"$file"

स्क्रिप्ट में, आपको आमतौर पर डिफ़ॉल्ट रूप से बंद >|होने की आवश्यकता नहीं होती है noclobber


xpg_echo को इंगित करने के लिए धन्यवाद, यह वास्तव में एक समस्या है जो मुझे अपने कोड में कहीं और थी और इसका एहसास भी नहीं था। पुन: noclobber, मुझे अपने bashrc में इसे चालू करने की आदत है।
डेविड सूथर

0

यह वही करेगा जो आप चाहते हैं:

( while read -r -d '' ; do
    printf %s'\0' "${REPLY}" ;
  done ;

  # When read hits EOF, it returns non-zero which exits the while loop.
  # That data still needs to be output:
  printf %s "${REPLY}"
) >> ${file}

स्मृति उपयोग पर ध्यान दें। यह एक शून्य-सीमांकित फैशन में इनपुट पढ़ता है।

यदि इनपुट में कोई \0 अशक्त बाइट्स नहीं हैं , तो बैश को पहले इनपुट की पूरी सामग्री को मेमोरी में पढ़ने की आवश्यकता होगी, और फिर इसे आउटपुट करें।

अपने छोटे कदम के बारे में:

echo -n '' >| "$file" #Truncate the file

बहुत सरल और समकक्ष है:

> ${file}   #Truncate the file
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.