क्या मैं जगह में एक फ़ाइल को बदल सकता हूं?


17

manपेज मुझे ज्यादा आशा नहीं देता है, लेकिन मैं इसे एक undocumented (और / या ग्नू विशेष) सुविधा है उम्मीद कर रहा हूँ।

जवाबों:


15

आप नहीं कर सकते। या तो एड या जीएनयू सेड या पर्ल का उपयोग करें, या वे पर्दे के पीछे क्या करते हैं, जो सामग्री के लिए एक नई फ़ाइल बनाना है।

ed, पोर्टेबल:

ed foo <<EOF
1,$s/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/
w
q
EOF

जीएनयू sed :

sed -i -e 's/^\([^,]*\),\([^,]*\),\([^,]*\).*/\1,\3/' foo

पर्ल:

perl -i -l -F, -pae 'print @F[1,3]' foo

cutएक नई फ़ाइल बनाना (अनुशंसित, क्योंकि यदि आपकी स्क्रिप्ट बाधित है, तो आप इसे फिर से चला सकते हैं):

cut -d , -f 1,3 <foo >foo.new &&
mv -f foo.new foo

cut, जगह में फ़ाइल की जगह और के स्वामित्व और अनुमति बरकरार रखती है foo , लेकिन रुकावट के खिलाफ सुरक्षा की जरूरत है):

cp -f foo foo.old &&
cut -d , -f 1,3 <foo.old >foo &&
rm foo.old

मैं cut-based तरीकों में से एक का उपयोग करने की सलाह देता हूं । इस तरह आप किसी भी गैर-मानक उपकरण पर निर्भर नहीं होते हैं, आप नौकरी के लिए सबसे अच्छे उपकरण का उपयोग कर सकते हैं, और आप व्यवधान पर व्यवहार को नियंत्रित कर सकते हैं।


.oldइन-प्लेस परिवर्तनों के लिए विधि की तुलना में बेहतर ,echo "$(cut -d , -f 1,3 <foo)" > foo
जिप्सीकोस्मोनॉट

1
@GypsyCosmonaut नहीं, यह "बेहतर" नहीं है। यह अधिक नाजुक है। इसका एकमात्र लाभ यह है कि यह टाइप करने के लिए छोटा है। आपकी विधि के साथ मुख्य समस्या यह है कि यदि इनपुट फ़ाइल को संसाधित करते समय या आउटपुट लिखते समय कोई त्रुटि होती है, तो डेटा खो जाता है। यह बाइनरी डेटा के साथ भी काम नहीं करता है: आउटपुट को पहले नल बाइट पर छोटा किया जाएगा। पाठ फ़ाइलों के साथ भी, यह फ़ाइल के अंत से खाली लाइनों को हटा देता है। बड़ी फ़ाइलों के साथ, यह विफल हो सकता है क्योंकि डेटा को शेल की मेमोरी में स्ट्रिंग के रूप में संग्रहीत किया जाना है (और याद रखें, यदि ऐसा होता है, तो डेटा खो जाता है)।
गिल्स एसओ- बुराई को रोकना '26

ऊ धन्यवाद, मुझे नहीं पता था कि अशक्त बाइट के साथ समस्याएं हो सकती हैं
जिप्सीकोस्मोनॉट

मुझे लगता है कि यह सरल है:cut -d , -f 1,3 foo > foo.new rm foo mv foo.new foo
LoMaPh

@LoMaPh वास्तव में, मुझे नहीं पता कि मैंने पुरानी फ़ाइल का नाम क्यों बदला: नई फ़ाइल का नाम बदलने से इसका कोई लाभ नहीं है। यह सरल भी है क्योंकि आपको चरण की आवश्यकता नहीं है rm foo। और आपको कॉल नहीं करना चाहिए rm foo, क्योंकि mv foo.new fooयह परमाणु है: यह पुराने संस्करण को हटा देता है और एक ही समय में नए संस्करण को रखता है।
गिल्स एसओ- बुराई को रोकना '

24

Moreutils ubuntu (और यह भी से पैकेज डेबियन ) नामक एक कार्यक्रम है sponge, जो तरह-की भी अपनी समस्या का हल।

आदमी स्पंज से:

स्पंज मानक इनपुट पढ़ता है और इसे निर्दिष्ट फ़ाइल पर लिखता है। शेल पुनर्निर्देशित के विपरीत, स्पंज आउटपुट फ़ाइल खोलने से पहले अपने सभी इनपुट को भिगो देता है। यह उन पाइपलाइनों को संकुचित करने की अनुमति देता है जो उसी फ़ाइल से पढ़ते हैं और लिखते हैं।

जो आपको कुछ ऐसा करने देगा:

cut -d <delim> -f <fields> somefile | sponge somefile

9

मुझे नहीं लगता कि cutअकेले उपयोग करना संभव है । मैं इसे आदमी या जानकारी पृष्ठ में नहीं ढूँढ सका। आप ऐसा कुछ कर सकते हैं

mytemp=$(mktemp) && cut -d" " -f1 file > $mytemp && mv $mytemp file

mktempआपको एक अपेक्षाकृत सुरक्षित अस्थायी फ़ाइल बनाता है जिसे आप cutआउटपुट में पाइप कर सकते हैं ।


1

वीम-वे आज़माएँ:

$ ex -s +'%!cut -c 1-10' -cxa file.txt

यह फ़ाइल को जगह में संपादित करेगा (इसलिए बैकअप पहले करें)।

वैकल्पिक रूप से उपयोग grep, sedया gawk



0

ठीक है, क्योंकि cutयह कम उत्पादन से पढ़ता है, आप कर सकते हैं:

cut -c1 < file 1<> file

यही है, इसकी स्टडी को fileरीड-ओनली मोड में ओपन करें और इसकी स्टडआउट fileको ट्रंकेशन ( <>) के बिना रीड + राइट मोड में ओपन करें ।

इस तरह, cutकेवल फ़ाइल को अपने आप से अधिलेखित कर देगा। हालांकि, यह बाकी फाइल को अछूता छोड़ देगा। उदाहरण के लिए, यदि fileइसमें शामिल हैं:

foo
bar

आउटपुट बन जाएगा:

f
b
bar

f\nb\nजगह ले ली है foo\n, लेकिन barअभी भी वहाँ है। cutसमाप्त होने के बाद आपको फ़ाइल को छोटा करना होगा ।

इसके साथ ksh93, आप इसे अपने <>;ऑपरेटर के साथ कर सकते हैं जो इस तरह के कार्य करता है <>कि यदि कमांड सफल होता है, ftruncate()तो इसे फाइल डिस्क्रिप्टर पर बुलाया जाता है। इसलिए:

cut -c1 < file 1<>; file

अन्य गोले के साथ, आपको ftruncate()कुछ अन्य माध्यमों से करने की आवश्यकता होगी जैसे:

{ cut -c1 < file; perl -e 'truncate STDOUT, tell STDOUT';} 1<> file

हालाँकि perlइसके लिए बस थोड़ा सा ओवरकॉक करना विशेष रूप से यहाँ पर विचार perlकरना है जो आसानी से ऐसा कर सकता है cutजैसे:

perl -pi -e '$_ = substr($_, 0, 1)' file

खबरदार कि अगर इन सभी तरीकों से वास्तविक इन-री-री राइटिंग शामिल है, यदि ऑपरेशन बीच में बाधित होता है, तो आप एक दूषित फ़ाइल के साथ समाप्त हो जाएंगे। एक अस्थायी दूसरी फ़ाइल का उपयोग इस समस्या से बचा जाता है।

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