ফাইল থেকে নির্দিষ্ট লাইন (এন, এন + 4, এন + 8, এন + 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/… জিএনইউ সেডের সাহায্যে আপনি করতে পারেনsed -n '1~4p'
সন্দীপ

উত্তর:


28

AWK ব্যবহার:

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

পাঠকদের অনুশীলন হিসাবে কীভাবে এটি কাজ করে তা নির্ধারণ করা।


এই শর্ট অ্যাজক কোর্সের জন্য ধন্যবাদ!
darxmurf

20
NR % 4 == 1আরও সুস্পষ্ট আইএমও হতে পারে।
স্টাফেন চেজেলাস

12
@ স্টাফানে সম্মত; এটি সম্ভবত আমার পক্ষে প্রশ্নবিদ্ধ, তবে সম্ভাব্য হোম ওয়ার্ক প্রশ্নগুলির জন্য আমি আমার উত্তরগুলিকে কিছুটা অবিচ্ছিন্ন করার চেষ্টা করি ...
স্টিফেন কিট

@ স্টেফেনকিট আপনার উত্তরগুলিকে অস্পষ্ট করে? সত্যি? এটি করার জায়গা নয়।
ডেটা

22

split (জিএনইউ কোর্টিল) ব্যবহার করে :

split -nr/1/4 input > output
  • -nCHUNKSআউটপুট ফাইল উত্পন্ন

এবং CHUNKSহিসাবে

  • r/K/N বিভক্ত লাইন / রেকর্ড ছাড়াই স্ট্যান্ডআউটে রাউন্ড রবিন বিতরণ এবং কেবলমাত্র আউটপুট কেট ব্যবহার করুন

1
মন ফুঁকছে। এর মত উত্তরগুলি কেন আমি এই এসই পছন্দ করি। ধন্যবাদ!
ব্যবহারকারী 1717828

21

জিএনইউ সহ 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 এটি এত ঝরঝরে! এর আগে কখনই বুঝতে পারিনি; ভবিষ্যতে ব্যবহার করা হবে। এই উত্তরে এডিট নির্দ্বিধায়; অন্যান্য বাশ উত্তরগুলি (বিশেষত এটি ) অবশ্যই যাওয়ার উপায় হওয়ায় আমি এটি অপ্টিমাইজেশন সহ সত্যই বজায় রাখতে যাচ্ছি না ।
ব্যবহারকারী 1717828

আপনি যদি ব্যবহার করতে চলেছেন 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: অ্যারে এটি আকারে 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 লাইন থেকে শুরু করে প্রতি চতুর্থ লাইনটি মুদ্রণের জন্য একই কমান্ডটি ব্যবহার করতে পারেন তবে আপনি inputএটি খাওয়ানোর আগে আপনাকে 3, 2, বা 1 টি লাইন প্রিপেন্ড করতে হবে mapfile, যা আমি মনে করি এটির তুলনায় আরও বেশি সমস্যা ।

এটিও কাজ করে:

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

এখানে, একবারে printfঅ্যারের চারটি এন্ট্রি গ্রহণ করা হয় lines, কেবল প্রথমটি মুদ্রণ করে এবং অন্য তিনটি দিয়ে এড়িয়ে যান %.0s। আমি এটি পছন্দ করি না যেহেতু আপনাকে বিভিন্ন বিরতি বা শুরুর পয়েন্টগুলির জন্য বিন্যাসের স্ট্রিংয়ের সাথে ম্যানুয়ালি ঝাঁকুনি দিতে হয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.