किसी फ़ाइल से एकाधिक रिक्त लाइनें कैसे निकालें?


14

मेरे पास कुछ टेक्स्ट-फाइल्स हैं, जिनका उपयोग मैं नोट्स लेने के लिए करता हूं - सिर्फ सादा टेक्स्ट, आमतौर पर सिर्फ उपयोग करने के लिए cat >> file। कभी-कभी मैं एक नया विषय / लाइन ऑफ़ थिंक निर्दिष्ट करने के लिए एक रिक्त लाइन या दो (सिर्फ रिटर्न - नई लाइन वर्ण) का उपयोग करता हूं। प्रत्येक सत्र के अंत में, फ़ाइल को Ctrl+ के साथ बंद करने से पहले D, मैं आमतौर पर सत्रों को अलग करने के लिए बहुत सारी (5-10) रिक्त लाइनें (रिटर्न-कुंजी) जोड़ देता हूं।

यह स्पष्ट रूप से बहुत चालाक नहीं है, लेकिन यह इस उद्देश्य के लिए मेरे लिए काम करता है। मैं करना खत्म हुआ लेकिन बहुत सारे और अनावश्यक रिक्त लाइनों के बहुत सारे के साथ, तो मैं दूर करने के लिए एक तरह से तलाश कर रहा हूँ (के सबसे) अतिरिक्त लाइनें। क्या लिनक्स-कमांड (कट, पेस्ट, grep, ...?) है जिसे कुछ विकल्पों के साथ सीधे इस्तेमाल किया जा सकता है? वैकल्पिक रूप से, क्या किसी को एक sed, awk या perl (किसी भी स्क्रिप्टिंग-भाषा में अच्छी तरह से वास्तव में एक विचार है, हालांकि मैं sed या awk) स्क्रिप्ट पसंद करूँगा जो कि मुझे चाहिए? C ++ में कुछ लिखना (जो मैं वास्तव में खुद कर सकता था), बस ओवरकिल जैसा लगता है।

केस # 1: मुझे जो चाहिए वह एक स्क्रिप्ट / कमांड है जो दो (3 या अधिक) लगातार खाली लाइनों को हटा देगा, और उन्हें केवल दो खाली लाइनों के साथ बदल देगा। हालाँकि यह अच्छा होगा यदि इसे एक लाइन (2 या अधिक) को हटाने और / या केवल एक खाली लाइन के साथ कई रिक्त लाइनों को बदलने के लिए ट्वीक किया जा सकता है।

केस # 2: मैं एक स्क्रिप्ट / कमांड का उपयोग भी कर सकता था, जो टेक्स्ट की दो लाइनों के बीच एक सिंगल ब्लैंक लाइन को हटा देगा , लेकिन कई ब्लैंक लाइनों को छोड़ देगा (हालांकि खाली लाइनों में से किसी एक को हटाना भी स्वीकार्य होगा)।



2
@ l0b0, यह पूरी तरह से एक अलग सवाल है (अन्य एक एक था vim, और एक खाली लाइन के साथ रिक्त लाइनों को बदलने के लिए था)।
स्टीफन चेज़लस

जवाबों:


14

मामला एक:

awk '!NF {if (++n <= 2) print; next}; {n=0;print}'

केस 2:

awk '!NF {s = s $0 "\n"; n++; next}
     {if (n>1) printf "%s", s; n=0; s=""; print}
     END {if (n>1) printf "%s", s}'

Sed के बजाय awk के लिए +1
Rob

चूंकि यह उपयोग का मामला अक्सर दोहराया जाता है, इसलिए मैं एक स्क्रिप्ट बनाने का सुझाव दूंगा।
ChuckCottrill

15

आप uniqरिक्त लाइनों के कई उदाहरणों को एक रिक्त पंक्ति में संक्षिप्त करने के लिए उपयोग कर सकते हैं , लेकिन यह उन पंक्तियों को भी ध्वस्त कर देगा जिनमें पाठ होते हैं यदि वे समान हैं और एक दूसरे के नीचे हैं।


6

मामला एक:

perl -i -ane '$n=(@F==0) ? $n+1 : 0; print if $n<=2'

केस 2:

perl -i -ane '$n=(@F==0) ? $n+1 : 0; print $n==2 ? "\n$_" : $n==1 ? "" : $_ '

+1 पर्ल फुट! अक्क इसके लिए (शायद) विहित है, लेकिन (DRY) मुझे इस तरह के दोहराए जाने वाले उपयोग-मामलों की स्क्रिप्ट लिखने के लिए मजबूर करता है।
१०:४२

3

आप GNU sed के साथ केस # 1 को इस तरह संबोधित कर सकते हैं:

sed -r ':a; /^\s*$/ {N;ba}; s/( *\n *){2,}/\n\n/'

यही है, पैटर्न स्पेस में खाली लाइनों को इकट्ठा करें, और अगर तीन या अधिक से अधिक लाइनें हैं, तो इसे दो लाइनों तक कम करें।

केस # 2 की तरह, एकल-स्पैन्ड लाइनों में शामिल होने के लिए, आप इसे इस तरह से कर सकते हैं:

sed -r '/^ *\S/!b; N; /\n *$/!b; N; /\S *$/!b; s/\n *\n/\n/'

या टिप्पणी के रूप में:

sed -r '
  /^ *\S/!b        # non-empty line
  N                # 
  /\n *$/!b        # followed by empty line
  N                # 
  /\S *$/!b        # non-empty line
  s/\n *\n/\n/     # remove the empty line
'

1

यह समाधान फ़ाइल की अंतिम रिक्त लाइनों का भी ध्यान रखता है:

sed -r -n '
  /^ *$/!{p;b}  # non-blank line - print and next cycle
  h             # blank line - save it in hold space
  :loop
  $b end        # last line - go to end
  n             # read next line in pattern space
  /^ *$/b loop  # blank line - loop to next one
  :end          # pattern space has non-blank line or last blank line
  /^ *$/{p;b}   # last blank line: print and exit
  H;x;p         # non-blank line: print hold + pattern space and next cycle
'

0

"यूनीक" का उपयोग करने के लिए एंथन के सुझाव के बाद ...

खाली लाइनों की अग्रणी, अनुगामी और डुप्लिकेट निकालें।

# Get large random string.
rand_str=; while [[ ${#rand_str} -lt 40 ]]; do rand_str=$rand_str$RANDOM; done

# Add extra lines at beginning and end of stdin.
(echo $rand_str; cat; echo $rand_str) |

# Convert empty lines to random strings.
sed "s/^$/$rand_str/" |

# Remove duplicate lines.
uniq |

# Remove first and last line.
sed '1d;$d' |

# Convert random strings to empty lines.
sed "s/$rand_str//"

एक लंबी लाइन में:

(rand_str=; while [[ ${#rand_str} -lt 40 ]]; do rand_str=$rand_str$RANDOM; done; (echo $rand_str; cat; echo $rand_str) | sed "s/^$/$rand_str/" | uniq | sed '1d;$d' | sed "s/$rand_str//")

या बस "कैट-एस" का उपयोग करें।

मैं कोष्ठक से घुंघराले ब्रेसिज़ के लिए स्विच किया ताकि वर्तमान शेल संदर्भ में रहूं जो मुझे लगता है कि अधिक कुशल है। ध्यान दें कि अंतिम आदेश के बाद घुंघराले ब्रेसिज़ को अर्धविराम की आवश्यकता होती है और अलगाव के लिए जगह की आवश्यकता होती है।

# Add extra blank lines at beginning and end.
# These will be removed in final step.
{ echo; cat; echo; } |

# Replace multiple blank lines with a single blank line.
cat -s |

# Remove first and last line.
sed '1d;$d'

एक ही लाइन में।

{ { echo; cat; echo; } | cat -s | sed '1d;$d'; }

0

पोस्ट किए गए समाधान मुझे थोड़ा सा गुप्त लग रहा था। यहाँ Python 3.6 में समाधान है:

#!/usr/bin/env python3

from pathlib import Path                                                                                                                                                              
import sys                                                                                                                                                                            
import fileinput                                                                                                                                                                      


def remove_multiple_blank_lines_from_file(path, strip_right=True): 
    non_blank_lines_out_of_two_last_lines = [True, True] 
    for line in fileinput.input(str(path), inplace=True): 
        non_blank_lines_out_of_two_last_lines.pop(0) 
        non_blank_lines_out_of_two_last_lines.append(bool(line.strip())) 
        if sum(non_blank_lines_out_of_two_last_lines) > 0: 
            line_to_write = line.rstrip() + '\n' if strip_right else line 
            sys.stdout.write(line_to_write)


def remove_multiple_blank_lines_by_glob(rglob='*', path=Path('.'), strip_right=True): 
    for p in path.rglob(rglob): 
        if p.is_file(): 
            try:
                remove_multiple_blank_lines_from_file(p, strip_right=strip_right)
            except Exception as e:
                print(f"File '{p}' was not processed due the error: {e}")


if __name__ == '__main__':
    remove_multiple_blank_lines_by_glob(sys.argv[1], Path(sys.argv[2]), next(iter(sys.argv[3:]), None) == '--strip-right')

आप एक दुभाषिया से कार्यों को कॉल कर सकते हैं या इसे शेल से चला सकते हैं जैसे:

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