फ़ाइल से कुछ पंक्तियों (n, n + 4, n + 8, n + 12…) का चयन कैसे करें?


11

इनपुट:

1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4

अपेक्षित उत्पादन:

1
2
3
4

इसलिए, मुझे आउटपुट फ़ाइल में फ़ाइल का केवल 1, 5 वां, 9 वां, 13 वां मान होना चाहिए। यह कैसे करना है?


2
इसे भी देखें: unix.stackexchange.com/questions/325985/… GNU sed के साथ, आप कर सकते हैंsed -n '1~4p'
Sundeep

जवाबों:


28

AWK का उपयोग करना:

awk '!((NR - 1) % 4)' input > output

यह पता लगाना कि पाठक के लिए यह एक अभ्यास के रूप में कैसे छोड़ा जाता है।


इस छोटे से awk कोर्स के लिए धन्यवाद!
darxmurf

20
NR % 4 == 1अधिक सुपाठ्य IMO होगा।
स्टीफन चेजेलस

12
सहमत @ स्टीफन; यह शायद मेरी ओर से संदेहास्पद है, लेकिन संभावित होमवर्क के सवालों के लिए मैं अपने जवाबों को थोड़ा बाधित करने की कोशिश करता हूं ...
स्टीफन किट

@StephenKitt आपके जवाबों को मानता है? वास्तव में? यह ऐसा करने का स्थान नहीं है।
डेटा

22

का उपयोग कर split (GNU coreutils):

split -nr/1/4 input > output
  • -nCHUNKSआउटपुट फ़ाइलें उत्पन्न करें

और के CHUNKSरूप में

  • r/K/N राउंड रॉबिन वितरण और केवल आउटपुट K का उपयोग करें N का बंटवारा लाइनों / रिकॉर्ड के बिना stdout करने के लिए

1
होश उड़ जाना। इस तरह के उत्तर क्यों मुझे इस एसई से प्यार है। धन्यवाद!
user1717828

21

GNU के साथ sed:

sed '1~4!d' < input > output

मानक के साथ sed:

sed -n 'p;n;n;n' < input > output

साथ 1और 4में $nऔर $iचर:

sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'

7

अनिवार्य पर्ल समाधान जोड़ना:

perl -ne 'print if $. % 4 == 1' input > output

4

पायथन संस्करण, सिर्फ मनोरंजन के लिए:

with open('input.txt') as f:
    for i, line in enumerate(f.readlines()):
        if i%4 == 0:
            print(line.strip())

enumerate(f)कम मेमोरी का उपभोग करते हुए काम करने में सक्षम होना चाहिए
इरुवर

@iruvar यह बहुत साफ है! पहले कभी एहसास नहीं हुआ; भविष्य में उपयोग किया जाएगा। इसे इस उत्तर में संपादित करने के लिए स्वतंत्र महसूस करें; मैं वास्तव में अनुकूलन के साथ इसे बनाए रखने नहीं जा रहा हूं क्योंकि अन्य बैश उत्तर (विशेष रूप से यह एक ) निश्चित रूप से जाने का रास्ता है।
user1717828

यदि आप उपयोग करने जा रहे हैं readlines(इसलिए पूरी फ़ाइल को मेमोरी में खिसकाते हैं), तो आप f.readlines()[::4]हर चौथी पंक्ति को प्राप्त करने के लिए उपयोग कर सकते हैं । तो आप उपयोग कर सकते हैं print(''.join(f.readlines()[::4]))
निक

3

POSIX sed: यह विधि पॉज़िक्ली सीड का उपयोग करती है और इसलिए इसे हर जगह चलाया जा सकता है, या पॉज़िक का सम्मान करने वाले उन सेड्स को कम से कम चलाया जा सकता है।

 $ sed -ne '
   /\n/!{
    H;s/.*//;x
   }

   :loop
       $bdone
       N;s/\n/&/4
       tdone
   bloop

   :done
   s/.//;P
 ' input.file

एक और स्केलेबिलिटी उद्देश्यों के लिए प्रोग्रामेटिक सेड कोड जनरेशन है:

$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file

Perl: हम सरणी A को तब तक भरते हैं जब तक उसका आकार 4 न हो। फिर हम इसके पहले तत्व को प्रिंट करते हैं और साथ ही एरे को भी साफ करते हैं।

$ perl -pe '
   $A[@A] = @A ? <> : $_ while @A < 4;
   $_ = (splice @A)[0];
' input.file

1

scriptname filename skip(अपने मामले में 4) के साथ कॉल करें। यह iterफ़ाइल के शीर्ष से लाइनें खींचकर काम करता है और फिर केवल अंतिम आउटपुट देता है। यह तब तक वृद्धि करता iterहै skipsऔर तब तक दोहराता है जब तक कि मूल्य iterउस linesसे अधिक न हो जाए file

#!/bin/bash
file="$1"
lines=`wc -l < "$file"`
skips="$2" || "4"
iter=1
while [ "$iter" -le "$lines" ]; do
 head "$file" -n $iter | tail -n 1
 iter=$(( $iter + $skips ))
done

1

शुद्ध बैश:

mapfile -t lines < input
for (( i=0; i < ${#lines[@]}; i+=4 ))
do printf "%s\n" "${lines[$i]}"
done

मेपफाइल बैश 4 में जोड़ा गया एक बिलियन है जो मानक इनपुट को एक सरणी में पढ़ता है, यहां नाम दिया गया है lines, जिसमें एक प्रविष्टि प्रति पंक्ति है। -tविकल्प अंतिम नई-पंक्तियों स्ट्रिप्स।

यदि आप लाइन 4 से शुरू होने वाली हर चौथी लाइन को प्रिंट करना चाहते हैं, तो आप कर सकते हैं कि एक कमांड में mapfileकॉलबैक ऑप्शन का उपयोग करके -C, जो दिए गए कोड को इतनी सारी लाइनों को चलाता है, जिसके द्वारा दिए गए अंतराल के साथ -c। वर्तमान सरणी सूचकांक और सौंपी जाने वाली अगली पंक्ति को तर्क के रूप में कोड को दिया जाता है।

mapfile -t -c4 -C 'printf "%.0s%s\n"' < input

यह printfबिलिन का उपयोग करता है ; प्रारूप कोड %.0sपहले तर्क (इंडेक्स) को दबा देता है, इसलिए केवल रेखा मुद्रित होती है।

आप पंक्ति 1, 2, या 3 से शुरू होने वाली प्रत्येक चौथी पंक्ति को प्रिंट करने के लिए एक ही कमांड का उपयोग कर सकते हैं, लेकिन आपको इसे फीड करने से पहले 3, 2, या 1 लाइनों को inputपूर्व-निर्धारित करना होगा mapfile, जो मुझे लगता है कि इसके लायक होने से अधिक परेशानी है ।

यह भी काम करता है:

mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"

यहां, एक बार में printfचार प्रविष्टियों की खपत होती है lines, केवल पहले को प्रिंट करना और अन्य तीन को छोड़ देना %.0s। मुझे यह पसंद नहीं है क्योंकि आपको अलग-अलग अंतराल या शुरुआती बिंदुओं के लिए प्रारूप स्ट्रिंग के साथ मैन्युअल रूप से फ़ेड करना है।

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