फाइल पढ़ना और लिखना: टी कमांड


10

यह सर्वविदित है कि इस तरह एक आदेश है:

cat filename | some_sed_command >filename

er फ़ाइल फ़ाइल नाम, आउटपुट पुनर्निर्देशन के रूप में, कमांड से पहले निष्पादित किया जा रहा है, फ़ाइल नाम को काट दिया जाता है।

कोई निम्नलिखित तरीके से समस्या को हल कर सकता है:

cat file | some_sed_command | tee file >/dev/null

लेकिन मुझे यकीन नहीं है कि यह किसी भी मामले में काम करेगा: क्या होगा यदि फ़ाइल (और sed कमांड का परिणाम) बहुत बड़ा है? ऑपरेटिंग सिस्टम कुछ सामग्री को ओवरराइट करने से कैसे बच सकता है जो अभी भी पढ़ा नहीं गया है? मैं देखता हूं कि एक स्पंज कमांड भी है जो किसी भी मामले में काम करना चाहिए: क्या यह टी की तुलना में "सुरक्षित" है?


आपका मुख्य लक्ष्य क्या है? (सरल शब्दों में)
सर्गी कोलोडियाज़नी

@ शेर बस यह समझें कि चीजें कैसे काम करती हैं ... kos द्वारा लिखित जवाब इस मामले को स्पष्ट करता है
VeryHardCoder

जवाबों:


10

कोई निम्नलिखित तरीके से समस्या को हल कर सकता है:

cat file | some_sed_command | tee file >/dev/null

नहीं

संभावना कम fileहो जाएगी, लेकिन इसकी कोई गारंटी cat file | some_sed_command | tee file >/dev/nullनहीं होगी file

यह सब इस बात पर निर्भर करता है कि कौन सी कमांड पहले संसाधित की गई है, जैसा कि किसी से क्या उम्मीद की जा सकती है, एक पाइप में कमांड को बाएं से दाएं संसाधित नहीं किया जाता है । इस बात की कोई गारंटी नहीं है कि किस कमांड को पहले उठाया जाएगा, इसलिए कोई भी इसे बस बेतरतीब ढंग से उठाया हुआ समझ सकता है और कभी भी इस पर भरोसा न करें कि आपत्तिजनक नहीं है।

चूंकि तीन आदेशों के बीच पहले से चुने जाने वाले आक्रामक आदेश की संभावनाएं कम होती हैं, इसलिए अपमानजनक कमान के लिए दो कमांडों के बीच पहले चुने जाने की संभावना कम होती है, यह कम संभावना है कि इसेfile छोटा कर दिया जाएगा, लेकिन यह अभी भी होने वाला है

script.sh:

#!/bin/bash
for ((i=0; i<100; i++)); do
    cat >file <<-EOF
    foo
    bar
    EOF
    cat file |
        sed 's/bar/baz/' |
        tee file >/dev/null
    [ -s file ] &&
        echo 'Not truncated' ||
        echo 'Truncated'
done |
    sort |
    uniq -c
rm file
% bash script.sh
 93 Not truncated
  7 Truncated
% bash script.sh
 98 Not truncated
  2 Truncated
% bash script.sh
100 Not truncated

इसलिए कभी भी कुछ ऐसा इस्तेमाल करें cat file | some_sed_command | tee file >/dev/nullspongeसुझाव के अनुसार ओली का उपयोग करें ।

एक विकल्प के रूप में, थोड़े वातावरण और / या अपेक्षाकृत छोटी फ़ाइलों के लिए कोई भी यहां एक स्ट्रिंग का उपयोग कर सकता है और किसी भी कमांड के चलने से पहले फ़ाइल को पढ़ने के लिए कमांड प्रतिस्थापन:

$ cat file
foo
bar
$ for ((i=0; i<100; i++)); do <<<"$(<file)" sed 's/bar/baz/' >file; done
$ cat file
foo
baz

9

के लिए sedविशेष रूप से, आप अपने उपयोग कर सकते हैं -iयथा-स्थान तर्क। यह सिर्फ खोली गई फ़ाइल को वापस बचाता है, जैसे:

sed -i 's/ /-/g' filename

यदि आप कुछ बीफ़ करना चाहते हैं, तो यह मानते हुए कि आप इससे अधिक कर रहे हैं sed, हाँ, आप sponge( moreutilsपैकेज से) पूरी चीज़ को बफर कर सकते हैं जो फ़ाइल को लिखने से पहले सभी स्टड को "सोख" देगा। यह teeकम कार्यक्षमता के साथ जैसा है लेकिन है। मूल उपयोग के लिए, हालांकि, यह ड्रॉप-इन प्रतिस्थापन में बहुत अधिक है:

cat file | some_sed_command | sponge file >/dev/null

क्या वह सुरक्षित है? निश्चित रूप से। संभवत: इसकी सीमा इतनी है कि यदि आप कुछ भारी काम कर रहे हैं (और इन-प्लेस को सेड के साथ संपादित नहीं कर सकते हैं), तो आप अपने संपादन को दूसरी फ़ाइल में करना चाहते हैं और फिर mvउस फ़ाइल को मूल फ़ाइल नाम में वापस कर सकते हैं। परमाणु होना चाहिए (ताकि इन फ़ाइलों के आधार पर कुछ भी टूट न जाए यदि उन्हें निरंतर उपयोग की आवश्यकता हो)।


0

आप पूर्व मोड में विम का उपयोग कर सकते हैं:

ex -sc '%!some_sed_command' -cx filename
  1. % सभी लाइनों का चयन करें

  2. ! चलाने के आदेश

  3. x सेव करके छोड़ो


0

ओह, लेकिन spongeएकमात्र विकल्प नहीं है; इसे moreutilsठीक से काम करने के लिए आपको प्राप्त करने की आवश्यकता नहीं है । कोई भी तंत्र तब तक काम करेगा जब तक वह निम्नलिखित दो आवश्यकताओं को पूरा नहीं करता है:

  1. यह आउटपुट फाइल के नाम को एक पैरामीटर के रूप में स्वीकार करता है।
  2. सभी इनपुट संसाधित होने के बाद यह केवल आउटपुट फ़ाइल बनाता है।

आप देखिए, ओपी की जिस सुप्रसिद्ध समस्या का जिक्र है, वह यह है कि शेल उन सभी फाइलों को बनाएगा जो पाइप के लिए काम करने के लिए आवश्यक हैं, यहां तक ​​कि पाइप लाइन में कमांड को निष्पादित करने के लिए शुरुआत से पहले, इसलिए यह वह शेल है जो वास्तव में छोटा हो जाता है आउटपुट फ़ाइल (जो दुर्भाग्य से इनपुट फ़ाइल भी है) कमांड से पहले किसी को भी निष्पादित करने का मौका मिला है।

teeआदेश काम नहीं करता, यहां तक कि यह संतुष्ट पहली आवश्यकता हालांकि, क्योंकि यह दूसरी आवश्यकता को पूरा नहीं करता है: यह हमेशा से शुरू होने के तुरंत बाद ही आउटपुट फ़ाइल बन जाएगा, ताकि यह सीधे आउटपुट फ़ाइल में एक पाइप बनाने के रूप में बुरा के रूप में अनिवार्य रूप से है। (यह वास्तव में बदतर है, क्योंकि इसका उपयोग आउटपुट फ़ाइल के टुकड़े-टुकड़े होने से पहले एक गैर-निर्धारक यादृच्छिक विलंब का परिचय देता है, इसलिए आप सोच सकते हैं कि यह काम करता है, जबकि वास्तव में यह नहीं करता है।)

इसलिए, इस समस्या को हल करने के लिए हम सभी को कुछ कमांड चाहिए जो किसी भी आउटपुट को बनाने से पहले उसके सभी इनपुट को बफर कर देगी, और जो आउटपुट फाइलनाम को एक पैरामीटर के रूप में स्वीकार करने में सक्षम है, ताकि हमें इसके आउटपुट को पाइप करने की आवश्यकता न हो आउटपुट फ़ाइल। ऐसा ही एक आदेश है shuf। तो, निम्नलिखित वही काम पूरा करेगा जो sponge:

    shuf --output=file --random-source=/dev/zero 

यह --random-source=/dev/zeroभाग shufबिना किसी फेरबदल के अपना काम करने की कोशिश करता है, इसलिए यह आपके इनपुट को बिना बदले ही बदल देगा।

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