কোনও ফাইলের প্রথম কয়েক এবং শেষ কয়েকটি লাইন প্রদর্শন করার কমান্ড


23

আমার কাছে অনেকগুলি সারি সহ একটি ফাইল রয়েছে এবং প্রতিটি সারিটির শুরুতে একটি টাইমস্ট্যাম্প থাকে, যেমন

[Thread-3] (21/09/12 06:17:38:672) logged message from code.....

সুতরাং, আমি প্রায়শই এই লগ ফাইল থেকে 2 টি জিনিস পরীক্ষা করি।

  1. প্রথম কয়েকটি সারি, এতে বৈশ্বিক পরিস্থিতি রয়েছে এবং শুরুর সময়ও দেওয়া হয়।
  2. সর্বশেষ কয়েকটি সারি, এর কিছু অন্যান্য তথ্যের সাথে প্রস্থান স্থিতি রয়েছে।

এমন কোন দ্রুত একা একক কমান্ড আছে যা আমাকে কোনও ফাইলের প্রথম এবং শেষ কয়েক লাইন প্রদর্শন করতে পারে?


2
বিশ্বব্যাপী অবস্থা কী, এবং আপনার পক্ষে head and tailকাজ করে না ?
ডেইজি

এটি আমার লগ ফাইলের অংশ। আমি বিশদ হওয়ার চেষ্টা করছিলাম। আপনি তা উপেক্ষা করতে পারেন।
এমটিকে

আপনার সমাধানটি আমার কাছে দুর্দান্ত দেখাচ্ছে। আপনি যদি আরও সুবিধা চান তবে এটি একটি শেল ফাংশন তৈরি করুন (এমনকি কোনও উপ নামও করতে পারে)।
ভনব্র্যান্ড

@ ভনব্র্যান্ড সমস্যা হ'ল আমি জানি নাN
বার্নহার্ড

@ বার্নহার্ড, আমি কোনও sed(1)বিশেষজ্ঞ নই , তবে এর সাথে পরে ব্যবহারের জন্য স্ট্যাশ স্ট্যাশিংয়ের উপায় রয়েছে। এটি এটি দেখার জন্য অর্থ প্রদান করে। ওও, আমি সম্ভবত একটি পার্ল (বা যাই হোক না কেন) স্ক্রিপ্টটি ঘন ঘন ব্যবহৃত হলে এটি করার জন্য চাবুক চাই, কারণ আমি এর সাথে আরও পরিচিত।
ভনব্র্যান্ড

উত্তর:


12

আপনি এটি ব্যবহার করতে sedবা awkএকটি কমান্ড দিয়ে তৈরি করতে পারেন । তবে আপনি গতিতে শিথিল হবেন, কারণ sedএবং awkযাইহোক পুরো ফাইলটি চালানো দরকার। গতির দৃষ্টিকোণ থেকে একটি ফাংশন করা বা প্রতিবার tail+ এর সংমিশ্রণ করা ভাল head। যদি ইনপুটটি পাইপ হয় তবে এটির কাজ না করার ক্ষতি রয়েছে, তবে আপনার শেলটি যদি সমর্থন করে তবে আপনি প্রোসেস সাবস্টিটিউশনটি ব্যবহার করতে পারেন (নীচের উদাহরণে দেখুন)।

first_last () {
    head -n 10 -- "$1"
    tail -n 10 -- "$1"
}

এবং ঠিক এটি চালু

first_last "/path/to/file_to_process"

প্রক্রিয়া প্রতিস্থাপন (বাশ, zsh, কেবলমাত্র শাঁসের মতো ksh) নিয়ে এগিয়ে যেতে:

first_last <( command )

গীত। এমনকি grepআপনার "বৈশ্বিক পরিস্থিতি" বিদ্যমান কিনা তা পরীক্ষা করতে আপনি একটি যুক্ত করতে পারেন।


-n 10ডিফল্ট, না?
l0b0

@ l0b0 হ্যাঁ, এটি ডিফল্ট। -n 10এখানে প্রয়োজন হয় না।
নলখাগড়া

20

@ ক্রুশ বড় ফাইলগুলির জন্য মাথা + লেজ আরও দক্ষ হওয়ার জন্য সঠিক, তবে ছোট ফাইলগুলির জন্য (<20 লাইন) কিছু লাইন দু'বার আউটপুট হতে পারে।

{ head; tail;} < /path/to/file

সমান দক্ষ হবে, তবে উপরে সমস্যা হবে না।


রাশ সমাধানের বিপরীতে, এটি পসিক্স শেলটিতে কাজ করে না।
মার্কো

2
@ মার্কো হাহ? এখানে কেবল পসিক্স কনস্ট্রাক্টস ব্যবহার করা হয়। আপনি কি ভুল হতে দেখছেন?
গিলস 'অসন্তুষ্ট হওয়া বন্ধ করুন'

2
@ গিলস আমি স্থানটি মিস করেছি: {head; tail;} < filezsh এ কাজ করে তবে sh এ ব্যর্থ হয়। { head; tail;} < fileসর্বদা কাজ করে। গোলমাল জন্য দুঃখিত।
মার্কো

@ মারকো, যদি এর সাথে সমস্যা হয় তবে তা headশেল নয়, সাথেই হত । পসিক্সের headনিয়মিত ফাইলগুলির জন্য 10 লাইন পেরিয়ে ফাইলটিতে কার্সারটি রেখে দেওয়া দরকার । নন-পসিক্স headবাস্তবায়নের জন্য একটি সমস্যা দেখা দিতে পারে (জিএনইউ হেডের খুব পুরানো সংস্করণ সেই উদাহরণে অ-অনুগত ছিল তবে আমরা কয়েক দশক ধরে কথা বলছি) অথবা যদি ফাইলটি সন্ধানযোগ্য না হয় (যেমন নামযুক্ত পাইপ বা সকেটের মতো, তবে তারপরে) অন্যান্য সমাধানেও একই সমস্যা হবে)।
স্টাফেন চেজেলাস

1
@ এফসিটিডব্লিউ,sudo sh -c '{ head; tail;} < /path/to/file'
স্টাফেন চেজেলাস

9

{ head; tail; }সমাধান পাইপ (অথবা সকেট বা অন্য কোন অ seekable ফাইল) কারণ কাজ করবে না headঅত্যধিক তথ্য গ্রাস পারে, যদি তা ব্লকগুলো দ্বারা সার্চ এবং সম্ভাব্য পরলোক ফাইল ভিতরে কার্সার রেখে একটি নল ফিরে চাইতে পারে না tailবোঝানো হয় নির্বাচন.

সুতরাং, আপনি এমন একটি সরঞ্জাম ব্যবহার করতে পারেন যা শেলগুলির মতো একটি সময়ে একটি অক্ষর পড়তে পারে read(এখানে এমন একটি ফাংশন ব্যবহার করে যা মাথার রেখা এবং লেজ রেখার সংখ্যা আর্গুমেন্ট হিসাবে গ্রহণ করে)।

head_tail() {
  n=0
  while [ "$n" -lt "$1" ]; do
    IFS= read -r line || { printf %s "$line"; break; }
    printf '%s\n' "$line"
    n=$(($n + 1))
  done
  tail -n "${2-$1}"
}
seq 100 | head_tail 5 10
seq 20 | head_tail 5

বা tailউদাহরণস্বরূপ awk মধ্যে বাস্তবায়ন :

head_tail() {
  awk -v h="$1" -v t="${2-$1}" '
    {l[NR%t]=$0}
    NR<=h
    END{
      n=NR-t+1
      if(n <= h) n = h+1
      for (;n<=NR;n++) print l[n%t]
    }'
}

সাথে sed:

head_tail() {
  sed -e "1,${1}b" -e :1 -e "$(($1+${2-$1})),\$!{N;b1" -e '}' -e 'N;D'
}

(যদিও সাবধান হন যে কিছু sedবাস্তবায়নগুলির তাদের প্যাটার্ন স্পেসের আকারের পরিমাণ কম রয়েছে, সুতরাং লেজ রেখার সংখ্যার বড় মানের ক্ষেত্রে ব্যর্থ হবে)।


4

bashপ্রক্রিয়া প্রতিস্থাপন ব্যবহার করে, আপনি নিম্নলিখিতটি করতে পারেন:

make_some_output | tee >(tail -n 2) >(head -n 2; cat >/dev/null) >/dev/null

নোট করুন যে লাইনগুলি যথাযথভাবে হওয়ার গ্যারান্টিযুক্ত নয়, যদিও ফাইলগুলি প্রায় 8 কেবি-র চেয়ে দীর্ঘতর, তবে সম্ভবত এটি হবে likely এই 8 কেবি কাটঅফটি রিড বাফারের টিপিকাল আকার এবং এটি সম্পর্কিত কারণটি | {head; tail;}ছোট ফাইলগুলির জন্য কাজ করে না।

cat >/dev/nullপালনে বাধ্য করা হবে headপাইপলাইন জীবিত। অন্যথায় teeতাড়াতাড়ি প্রস্থান করবে এবং আপনি যখন আউটপুট পাবেন তখন tailএটি শেষের পরিবর্তে ইনপুটটির মাঝামাঝি থেকে হবে।

অবশেষে, এর >/dev/nullপরিবর্তে কেন বলুন, tailঅন্যটিতে চলেছেন |? নিম্নলিখিত ক্ষেত্রে:

make_some_output | tee >(head -n 2; cat >/dev/null) | tail -n 2  # doesn't work

headtailকনসোলের চেয়ে পাইপকে স্টিডআউট খাওয়ানো হয়েছে , যা আমরা আদৌ চাই না।


যখন মাথা বা লেজগুলি আউটপুট চান তাদের লেখার কাজ শেষ করে, তারা তাদের স্টিডিনটি বন্ধ করে প্রস্থান করে। সেখান থেকে সিগপাইপ আসছে। সাধারণত এটি একটি ভাল জিনিস, তারা বাকি আউটপুটটি বাতিল করে দিচ্ছে, তাই পাইপের অপর পক্ষের এটি তৈরির সময় ব্যয় অব্যাহত রাখার কোনও কারণ নেই।
ডারোবার্ট

অর্ডারটিকে বহাল রাখার সম্ভাবনা কী করে? এটি সম্ভবত একটি বৃহত ফাইলের জন্য হবে, কারণ tailদীর্ঘ সময় ধরে কাজ করতে হবে তবে আমি আশা করি (এবং দেখুন) এটি সংক্ষিপ্ত ইনপুটগুলির জন্য প্রায় অর্ধেক সময় ব্যর্থ।
গিলস 'খারাপ হয়ে যাওয়া বন্ধ করুন'

আপনি পাইপগুলি tee >(head) >(tail)একই কারণে (একইভাবে >(...)zsh এবং বাশ উভয়ের দ্বারা সমর্থিত একটি ksh বৈশিষ্ট্য হিসাবে) যেগুলি দিয়ে সাইনপাইপ পাবেন। আপনি কাজ করতে পারে ... | (trap '' PIPE; tee >(head) >(tail) > /dev/null)কিন্তু আপনি এখনও কিছু দেখতে পাবেন ভাঙ্গা পাইপ থেকে ত্রুটি বার্তা tee
স্টাফেন চেজেলাস

আমার সিস্টেমে (৪.২.৩ash ব্যাশ, কোরিউটিলস ৮.১৩) tailহ'ল সিপাইপির দ্বারা নিহত ব্যক্তি হ'ল, না teeএবং পাইপেও tailলিখছেন না। সুতরাং এটি একটি থেকে হতে হবে kill(), ডান ?. এবং এটি কেবল তখনই ঘটে যখন আমি |বাক্য গঠন ব্যবহার করি । straceবলে যে teeডাকছে না kill()... তাই হয়তো bash?
Jender

1
@ জেন্ডার, আট কেকেরও বেশি খাওয়ানোর চেষ্টা করুনseq 100000 | tee >(head -n1) >(tail -n1) > /dev/null
স্টাফেন চ্যাজেলাস

3

ব্যবহার করে ed(যা পুরো ফাইলটি র‌্যামে পড়বে যদিও):

# cf. http://wiki.bash-hackers.org/howto/edit-ed
printf '%s\n' 'H' '1,10p' '$-10,$p' 'q' | ed -s file

সংক্ষিপ্ত:ed -s file <<< $'11,$-10d\n,p\nq\n'
don_crissti

2

কোনও ফাংশনে স্টিফেনের প্রথম সমাধান যাতে আপনি যুক্তিগুলি ব্যবহার করতে পারেন (কোনও বোর্নের মতো বা পোসিক্স শেলটিতে কাজ করে):

head_tail() {
    head "$@";
    tail "$@";
}

এখন আপনি এটি করতে পারেন:

head_tail -n 5 < /path/to/file

এটি অবশ্যই ধরে নিয়েছে যে আপনি কেবল একটি ফাইল দেখছেন এবং স্টিফেনের সমাধানগুলি কেবল নিয়মিত (সন্ধানযোগ্য) ফাইলগুলিতে কাজ করে (নির্ভরযোগ্যভাবে)।


2

GNU- এর -u( --unbuffered) বিকল্পের সাহায্যে sedআপনি sed -u 2qএটিতে অসমাপ্ত বিকল্প হিসাবে ব্যবহার করতে পারেন head -n2:

$ seq 100|(sed -u 2q;tail -n2)
1
2
99
100

(head -n2;tail -n2)শেষ লাইনগুলি গ্রাহিত ইনপুটটির ব্লকের অংশ হলে ব্যর্থ হয় head:

$ seq 1000|(head -n2;tail -n2)
1
2
999
1000
$ seq 100|(head -n2;tail -n2)
1
2

এটি শীর্ষ উত্তর হতে হবে! একটি যাদুমন্ত্র মত কাজ করে!
বেন উসমান

1

আমি আজকের এইরকম কিছুতে ছুটে এসেছি যেখানে আমার কেবল একটি স্রোতের সামনে থেকে শেষ লাইন এবং কয়েকটি লাইন প্রয়োজন এবং নিম্নলিখিতটি নিয়ে এসেছি।

sed -n -e '1{h}' -e '2,3{H}' -e '${H;x;p}'

আমি এটি এই হিসাবে পড়েছি: প্রথম লাইনের বিষয়বস্তু সহ হোল্ড স্পেসটি আরম্ভ করুন, হোল্ড স্পেসে লাইনগুলি 2-3টি সংযোজন করুন, হোল্ড স্পেসে শেষ লাইনটি সংযোজন করুন, ধরে রাখুন-এবং-প্যাটার্ন স্পেস করুন এবং প্যাটার্নটি মুদ্রণ করুন স্থান।

সম্ভবত sedআমার চেয়ে বেশি ফুফু কেউ এই প্রশ্নের মধ্যে নির্দেশিত স্ট্রিমের শেষ কয়েকটি লাইন প্রিন্ট করার জন্য কীভাবে এটি সাধারণ করতে হবে তা নির্ধারণ করতে পারে তবে আমার এটির প্রয়োজন ছিল না এবং $ঠিকানার উপর ভিত্তি করে গণিত করার কোনও সহজ উপায় খুঁজে পাইনি could মধ্যে sedঅথবা সম্ভবত হোল্ড স্থান তাই পরিচালনার যে শুধুমাত্র গত কয়েক লাইন যখন এটি হয় দ্বারা EOFউপনিত।


1

আপনি যদি এটি ইনস্টল করে থাকেন তবে পার্ল চেষ্টা করতে পারেন:

perl -e '@_ = <>; @_=@_[0, -3..-1]; print @_'

এটি বেশিরভাগ ফাইলের জন্য কাজ করবে, তবে প্রক্রিয়া করার আগে পুরো ফাইলটি মেমরির মধ্যে পড়ে। আপনি যদি পার্ল স্লাইসগুলির সাথে পরিচিত না হন তবে বর্গাকার বন্ধনীতে "0" এর অর্থ "প্রথম লাইন নিন", এবং "-3 ...- 1" এর অর্থ "শেষ তিনটি লাইন নিন"। আপনি উভয় আপনার প্রয়োজন অনুসারে উপযুক্ত করতে পারেন। আপনার যদি সত্যিই বড় ফাইলগুলি প্রক্রিয়া করতে হয় (যা 'বড়' তা আপনার র‌্যামের উপর নির্ভর করে এবং সম্ভবত অদলবদল হতে পারে), আপনি যেতে চাইতে পারেন:

perl -e 'while($_=<>){@_=(@_,$_)[0,-3..-1]}; print @_'

এটি কিছুটা ধীর হতে পারে, কারণ এটি প্রতিটি পুনরাবৃত্তিতে একটি টুকরো করে তবে এটি ফাইলের আকারে স্বতন্ত্র।

উভয় কমান্ডের পাইপগুলিতে এবং নিয়মিত ফাইলগুলির সাথে উভয়ই কাজ করা উচিত।

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