खोज के लिए सेड का विकल्प और बहुत लंबी लाइनों पर प्रतिस्थापित


9

मेरे पास ऐसी फाइलें हैं जो एक प्रोग्राम द्वारा उत्पन्न की गईं, जिन्होंने रिकॉर्ड के अंत में नई सुर्खियां नहीं बनाईं। मैं रिकॉर्ड्स के बीच नई कड़ियाँ डालना चाहता हूँ, और मैं एक सरल सेड स्क्रिप्ट के साथ ऐसा कर सकता हूँ:

sed -e 's/}{/}\n{/g'

समस्या यह है कि इनपुट फाइलें कई गीगाबाइट आकार में हैं, और इसलिए इनपुट लाइनों को sed करने के लिए लंबाई में कई GB हैं। sed स्मृति में एक रेखा रखने की कोशिश करता है, जो इस मामले में काम नहीं करता है। मैंने --unbufferedविकल्प की कोशिश की , लेकिन यह सिर्फ इसे धीमा बनाने के लिए लग रहा था और इसे सही तरीके से खत्म नहीं होने दिया।


क्या कुछ विचारों को आज़माने के लिए हमारे लिए कहीं एक उदाहरण इनपुट फ़ाइल अपलोड करना संभव होगा?
मारक

3
हो सकता है कि आप पहली बार इस्तेमाल कर सकते हैं trअनुवाद करने के लिए }में \nऔर उसके बाद का उपयोग sedएक जोड़ने के लिए }प्रत्येक पंक्ति के अंत में? इस तरह:tr '}' '\n' < your_file.txt| sed 's/$/}/'
user43791

फ़ाइल के अंत में एक नई पंक्ति जोड़ने से क्या मदद मिलती है? जैसे:printf "\n" >> file
नानी

1
@ कीतन, मैं 78 कचरा पात्रों के साथ एक फ़ाइल लिखने की बात दोहराता हूं, }{जब तक कि यह कई गीगाबाइट लंबे समय तक पर्याप्त न हो जाए।
नानी

@ ज्ञान - अच्छा बिंदु - लेकिन आपको 78 कहाँ मिलते हैं? यदि रिकॉर्ड पहले से ही अवरुद्ध हैं, तो dd if=file cbs=80 conv=unblockवह ऐसा करेगा - लेकिन यह शायद ही कभी इतना आसान है।
mikeserv

जवाबों:


7

आप एक अन्य टूल का उपयोग कर सकते हैं जो आपको इनपुट रिकॉर्ड विभाजक सेट करने देता है। उदाहरण के लिए

  • पर्ल

    perl -pe 'BEGIN{ $/="}{" } s/}{/}\n{/g' file
    

    विशेष चर $/इनपुट रिकॉर्ड विभाजक है। इसे }{समाप्त करने के रूप में लाइनों को परिभाषित करना }{। इस तरह आप पूरी चीज़ को बिना मेमोरी में पढ़े प्राप्त कर सकते हैं।

  • मवाल या गौक

    awk -v RS="}{" -vORS= 'NR > 1 {print "}\n{"}; {print}' file 
    

    यह एक ही विचार है। RS="}{"रिकॉर्ड विभाजक सेट करता है }{और फिर आप प्रिंट करते हैं }, एक नई {रेखा , (पहले रिकॉर्ड को छोड़कर) और वर्तमान रिकॉर्ड।


3

बचाव के लिए पर्ल:

perl -i~ -e ' $/ = \1024;
              while (<>) {
                  print "\n" if $closing and /^{/;
                  undef $closing;
                  s/}{/}\n{/g;
                  print;
                  $closing = 1 if /}$/;
              } ' input1 input2

फ़ाइल को 1024 बाइट्स के भाग में पढ़ने के $/लिए सेट करना \1024। जब $closingचर एक अंत में होता है }और अगले के साथ शुरू होता है, तो चर मामले को संभालता है {


1
+1, शायद सबसे अच्छा समाधान; अन्य perl / awk समाधान भी ठीक काम करते हैं लेकिन क्या होगा यदि पहला रिकॉर्ड विभाजक लगभग 17GB मूल्य के वर्ण के बाद होता है?
don_crissti

2

तुम्हें करना चाहिए:

{ <infile tr \} \\n;echo {; } | paste -d'}\n' - /dev/null >outfile

यह शायद सबसे कुशल समाधान है।

यह {}किसी भी संभावित डेटा की सुरक्षा के लिए एक डालता है । एक और trप्रक्रिया के साथ आप उस स्वैप कर सकते हैं और पहले {क्षेत्र के प्रमुख पर एक खाली लाइन कर सकते हैं । पसंद...

tr {} '}\n'| paste -d{\\0 /dev/null - | tr {}\\n \\n{}

तो सबसे पहले, डॉन के उदाहरण डेटा के साथ, यह करता है:

printf '{one}{two}{three}{four}' |
{ tr \} \\n; echo {; }           |
paste -d'}\n' - /dev/null
{one}
{two}
{three}
{four}
{}

... और दूसरा एक ...

printf '{one}{two}{three}{four}'      |
tr {} '}\n'| paste -d{\\0 /dev/null - |
tr {}\\n \\n{}
#leading blank
{one}
{two}
{three}
{four}

दूसरे उदाहरण के लिए कोई अनुगामी न्यूलाइन नहीं है - हालांकि पहले के लिए एक है।


0

बाइनरी sed-जैसी उपयोगिता कहा जाता हैbbe

मुझे इस मामले में sed-like syntax के साथ रहना आसान लगता है।

मैं बहुत का उपयोग करना पसंद bbeउपयोगिता (उपलब्ध अपने {uni, Linu} एक्स के पैकेज स्थापना, eq के माध्यम से apt-get)। या यहाँ अगर आप git भीड़ में से एक हैं, हालांकि मैंने व्यक्तिगत रूप से उस विशेष लिंक को वीट नहीं किया है।

1. यह s/before/after/मुहावरे का समर्थन करता है

यह एक "बाइनरी ब्लॉक एडिटर" है, जो sed-like (अन्य के बीच) संचालन का समर्थन करता है। इसमें सुपर कॉमन s/before/after/सबस्टेशन मुहावरा शामिल है जिसकी आपको आवश्यकता है। ध्यान दें, क्योंकि प्रति bbeदृष्टिकोण से कोई रेखाएं नहीं हैं , कमांड के अंत में कोई "ग्लोबल जी" नहीं है।

एक त्वरित परीक्षण के रूप में (आवश्यक नोट करें -e):

$ echo hello | bbe -e 's/l/(replaced)/'

पैदा करता है:

he(replaced)(replaced)o

2. अपने विशिष्ट मामले में }{करने के लिए }\n{रूपांतरण

तो अगर हम एक बड़े पैमाने पर (माना) प्रारूप में एक लाख की संख्या के साथ भरा फ़ाइल था {1}{2}{3}... {1000000}कोई गाड़ी रिटर्न के साथ, हम विनिमय कर सकते थे }{के साथ }\n{आसानी से, और सभी नंबरों को प्रत्येक पंक्ति में एक है।

यह इस bbeआदेश के साथ होगा :

bbe -e 's/}{/}\n{/'

जैसा कि इस zsh लूप में परीक्षण किया गया है, जिसे हम केवल पूंछ लेते हैं:

$ for ((num=0; num<1000000; num++)) do; echo -n "{$num}"; done | bbe -e 's/}{/}\n{/' | tail

जो इस का उत्पादन करेगा:

{999990}
{999991}
{999992}
{999993}
{999994}
{999995}
{999996}
{999997}
{999998}
{999999}

(निश्चित रूप से पीछे चलने वाली गाड़ी के बिना।)

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