মাথা এবং লেজ ব্যবহার করে বিভিন্ন সেট লাইন দখল করতে এবং একই ফাইলে সংরক্ষণ করা


10

সুতরাং এটি হোম ওয়ার্কের জন্য, তবে আমি নির্দিষ্ট হোমওয়ার্কের প্রশ্ন জিজ্ঞাসা করব না।

একটি ফাইল থেকে লাইন বিভিন্ন সেট দখল করতে আমার মাথা এবং লেজ ব্যবহার করতে হবে। সুতরাং 6-১১ এবং লাইনের 19-24 লাইনের মতো এবং উভয়টিকে অন্য একটি ফাইলে সংরক্ষণ করুন। আমি জানি আমি যেমন অ্যাপেন্ড ব্যবহার করে এটি করতে পারি

head -11 file|tail -6 > file1; head -24 file| tail -6 >> file1. 

তবে আমি মনে করি না যে আমাদের থাকার কথা।
আমি মাথা এবং লেজ কমান্ড একত্রিত এবং তারপরে ফাইলটিতে সংরক্ষণ করতে পারে এমন কোনও নির্দিষ্ট উপায় আছে?


1
তারা কি আপনাকে বিশেষভাবে ব্যবহার করতে বলছে headএবং tail? যদি তা হয় তবে আপনার সমাধানটি আপনি সবচেয়ে ভাল করতে পারেন। আপনি যদি অন্যান্য প্রোগ্রাম ব্যবহারের অনুমতি পেয়ে থাকেন, sedবা awkউত্তম সমাধানের জন্য অনুমতি দিতে পারেন (অর্থাত্ কম প্রক্রিয়া আমন্ত্রণের সাথে)।
n.st

হ্যাঁ, তারা আমাদের মাথা এবং লেজ ব্যবহার করার জন্য বলছে। আপনার উত্তর করার জন্য আপনাকে ধন্যবাদ।
ব্যবহারকারী2709291

আরও একটি জিনিস আমি যোগ করতে পারেন: আপনি সংযোজন আউটপুট ফেরৎ কাছাকাছি পেতে পারেন ( >>) বন্ধনীর মধ্যে দুই কমান্ড পরিক্ষেপ তাদের যোগসূত্র আউটপুট পুনর্নির্দেশ করতে দ্বারা: (head -11 file | tail -6; head -24 file | tail -6) > file1। এটি প্রকৃতপক্ষে ব্যক্তিগত পছন্দের দিকে নেমে আসে যা ভাল।
n.st

আপনাকে ধন্যবাদ যে খুব ভাল কাজ করবে। আমি সত্যিই এটার প্রশংসা করছি.
ব্যবহারকারী2709291

উত্তর:


11

আপনি headযদি একরকম এবং বেসিক পাটিগণিত দিয়ে এটি করতে পারেন , যদি আপনি এর { ... ; }মতো নির্মাণের সাথে কমান্ড গোষ্ঠী করেন

{ head -n ...; head -n ...; ...; } < input_file > output_file

যেখানে সমস্ত কমান্ড একই ইনপুট ভাগ করে দেয় (ধন্যবাদ @ মাইক্রোজার )।
6-11 এবং 19-24 রেখাগুলি পাওয়া সমান:

head -n 5 >/dev/null  # dump the first 5 lines to `/dev/null` then
head -n 6             # print the next 6 lines (i.e. from 6 to 11) then
head -n 7 >/dev/null  # dump the next 7 lines to `/dev/null` ( from 12 to 18)
head -n 6             # then print the next 6 lines (19 up to 24)

সুতরাং, মূলত, আপনি চালাতে হবে:

{ head -n 5 >/dev/null; head -n 6; head -n 7 >/dev/null; head -n 6; } < input_file > output_file

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

6

{ … }যৌগিক কমান্ডে পুনর্নির্দেশ অপারেটর প্রয়োগ করতে আপনি গ্রুপিং কনস্ট্রাক্ট ব্যবহার করতে পারেন ।

{ head -n 11 file | tail -n 6; head -n 24 file | tail -n 6; } >file1

প্রথম এম + এন লাইনগুলি সদৃশ করার পরিবর্তে এবং কেবল সর্বশেষ এন রাখার পরিবর্তে আপনি প্রথম এম লাইনগুলি এড়িয়ে যেতে পারেন এবং পরবর্তী এনটিকে নকল করতে পারেন large এটি বড় ফাইলগুলিতে পরিমাপযোগ্যভাবে দ্রুত । সাবধান থাকুন যে +Nআর্গুমেন্টটি tailএড়িয়ে যাওয়ার রেখার সংখ্যা নয়, তবে এটি একটি প্লাস - এটি 1 থেকে নম্বরযুক্ত লাইনগুলি মুদ্রণের জন্য প্রথম লাইনের সংখ্যা।

{ tail -n +6 file | head -n 6; tail -n +19 file | head -n 6; } >file1

যে কোনও উপায়ে, আউটপুট ফাইলটি কেবল একবার খোলা হয়, তবে প্রতিটি স্নিপেট বের করার জন্য ইনপুট ফাইলটি একবার ট্রভার করা হয়। ইনপুটগুলি গ্রুপিং সম্পর্কে কীভাবে?

{ tail -n +6 | head -n 6; tail -n +14 | head -n 6; } <file >file1

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

অন্য পদ্ধতির লাইনগুলি এড়ানোর জন্য headপাইপ ব্যবহার করা /dev/null

{ head -n 5 >/dev/null; head -n 6; head -n 7 >/dev/null; head -n 6; } <file >file1

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

কোনও ফাইল থেকে লাইনগুলির কয়েকটি ক্রম মুদ্রণের একটি সহজ উপায় হ'ল আরও সাধারণতাবাদী সরঞ্জাম যেমন শেড বা অ্যাজকে কল করা । (এটি ধীর হতে পারে তবে এটি কেবলমাত্র অত্যন্ত বড় ফাইলগুলির জন্য গুরুত্বপূর্ণ))

sed -n -e '6,11p' -e '19,24p' <file >file1
sed -e '1,5d' -e '12,18d' -e '24q' <file >file1
awk '6<=NR && NR<=11 || 19<=NR && NR<=24' <file >file1
awk 'NR==6, NR==11; NR==19, NR==24' <file >file1

2
এটি কাজ করে না , এটি আদর্শ, নির্দিষ্ট আচরণ - যদিও অবশ্যই আপনি বলেছেন, একটি পাইপ ভাগ করা ইনপুট জন্য একটি নির্ভরযোগ্য ইনপুট উত্স নয়ইউটিলিটি বর্ণনার ত্রুটি : যখন কোনও স্ট্যান্ডার্ড ইউটিলিটি একটি সন্ধানযোগ্য ইনপুট ফাইলটি পড়ে এবং ফাইলের শেষের দিকে পৌঁছানোর আগে কোনও ত্রুটি ছাড়াই বন্ধ করে দেয়, ইউটিলিটি নিশ্চিত করবে যে ওপেন ফাইলের বিবরণে ফাইলটি অফসেটটি যথাযথভাবে ঠিক করা হয়েছে যাতে প্রক্রিয়াজাত সর্বশেষ বাইটটি শেষ করা হয় past ইউটিলিটি
মাইক্রজারভ

2

আমি জানি আপনি বলেছিলেন যে আপনার মাথা এবং লেজ ব্যবহার করা উচিত, তবে সেড অবশ্যই এখানে কাজের সহজ সরঞ্জাম tool

$ cat foo
a 1 1
a 2 1
b 1 1
a 3 1
c 3 1
c 3 1
$ sed -ne '2,4p;6p' foo
a 2 1
b 1 1
a 3 1
c 3 1

এমনকি আপনি কিছু অন্যান্য প্রক্রিয়া সহ স্ট্রিংগুলিতে ব্লকগুলি তৈরি করতে পারেন এবং সেডের মাধ্যমে এটি চালাতে পারেন।

$ a="2,4p;6p"
$ sed -ne $a foo
a 2 1
b 1 1
a 3 1
c 3 1

-n আউটপুটকে অবহেলা করে, তারপরে আপনি পি দিয়ে মুদ্রণের জন্য ব্যাপ্তি নির্দিষ্ট করে, প্রথম এবং শেষ সংখ্যার সাহায্যে কমা দ্বারা পৃথক করা হয়।

বলা হচ্ছে, আপনি @ ডন_ক্রিসটি পরামর্শ দিয়েছিলেন এমন কমান্ডটি গ্রুপিং করতে পারবেন, বা প্রতিবার আপনি যখন যাবেন তখন মাথা / লেজ দিয়ে কয়েকবার ফাইলটি লুপ করুন।

$ head -4 foo | tail -3; head -6 foo | tail -1
a 2 1
b 1 1
a 3 1
c 3 1

একটি ফাইলের আরও লাইন এবং আপনার যত বেশি ব্লক রয়েছে, তত বেশি দক্ষ সিড পাবেন।


2

আপনার সাথে sed:

sed '24q;1,5d;12,18d' <infile >outfile

... সম্ভবত আরও কার্যকর সমাধান হতে পারে head। ডোন ইতিমধ্যে দেখিয়েছে যে এটি কীভাবে খুব ভালভাবে কাজ করতে পারে তবে আমি এটির সাথেও খেলছি। এই নির্দিষ্ট কেসটি পরিচালনা করতে আপনি কিছু করতে পারেন:

for   n in 5 6 7 6
do    head -n"$n" >&"$((1+n%2))"
done  <infile >outfile 2>/dev/null

... যা head4 বার লিখতে কল করবে outfileবা তার /dev/nullউপর নির্ভর করবে যে সেই পুনরাবৃত্তির মান $nএকটি সমান বা বিজোড় সংখ্যা কিনা on

আরও সাধারণ ক্ষেত্রে, আমি ইতিমধ্যে আমার কাছে থাকা অন্য কিছু জিনিস থেকে এটি একত্রে আবদ্ধ করেছি:

somehead()( 
### call it like:
### somehead -[repeat] [-][numlines]* <infile >outfile
    set -e -- "${1#-}" "$@"                             #-e for arg validation
    r=; cd -- "${TMP:-/tmp}"                            #go to tmp
    dd bs=4096 of="$$$$" <&4 2>&3 &                     #dd <in >tmpfile &bg
    until [ -s "$$$$" ]; do :; done                     #wait while tmpfile empty
    exec <"$$$$" 4<&-;   rm "$$$$"                      #<tmpfile; rm tmpfile
    [ "$3${1}0" -ne "$3${2#?}0" ]          ||           #validate args - chk $1
            shift "$(((r=-${1:--1})||1))"; shift        #shift 1||2
    while [ "$(((r+=(_n=1))-1))" -ne 0 ]   &&           #while ! $rptmax &&
          IFS= read -r l                   &&           #      ! EOF     &&
          printf "%.$(($1>0?${#l}+1:0))s" "$l           #      ? printf  do
";  do    for n do [ "${n#-}" -gt 0 ]      || exit      #args all -[nums>0]
          head "-n$((${n#-}-_n))" >&"$((n>(_n=0)?1:3))" #head -n?$1 >?[+-]
    done; done                                          #done and done
)   4<&0 3>/dev/null                                    #4<for dd 3>for head

এটি আপনার জিনিস যেমন করতে পারে:

 seq 100 | somehead -1 -5 6 -7 6

... যা ছাপায় ...

6
7
8
9
10
11
19
20
21
22
23
24

এটি আশা করে যে এটির প্রথম আরগটি একটি -, বা, ব্যর্থ হয়েছে, কেবল ক এর সাথে পূর্ববর্তিত পুনরাবৃত্তি গণনা হবে -। যদি কোনও গণনা সরবরাহ করা হয় তবে এটি নিম্নলিখিত বার্তাগুলিতে প্রদত্ত রেখার প্যাটার্নটি যতবার নির্দিষ্ট করা হয়েছে তার পুনরাবৃত্তি করবে এবং এটি করার সাথে সাথে এটি বন্ধ হয়ে যাবে।

নিম্নলিখিত প্রতিটি আর্গের জন্য এটি কোনও লাইন-কাউন্টকে নির্দেশ করতে একটি aণাত্মক পূর্ণসংখ্যার ব্যাখ্যা করবে যা একটি লিখন গণনা /dev/nullএবং একটি লিখন গণনা যা একটি লিখিত উচিত তা নির্দেশ করার জন্য ধনাত্মক পূর্ণসংখ্যার ব্যাখ্যা করবে stdout

সুতরাং উপরের উদাহরণে এটি প্রথম 5 টি লাইন প্রিন্ট করে /dev/null, পরের 6 থেকে stdoutপরেরটি, পরের 7 থেকে /dev/nullআবার এবং পরের 6 আবার একবার stdout। এর আরোগুলির শেষের দিকে পৌঁছে এবং -1পুনরাবৃত্ত গণনার মাধ্যমে পুরোপুরি চক্রাকারে চলে যাওয়ার পরে এটি প্রস্থান করে। প্রথম তর্কটি যদি হয় তবে -2এটি আরও একবার প্রক্রিয়াটি পুনরাবৃত্তি করতে পারে, বা -যতক্ষণ পারত।

প্রতিটি আরগ চক্রের জন্য whileলুপটি একবারের মাধ্যমে প্রক্রিয়া করা হয়। প্রতিটি লুপের শীর্ষে প্রথম লাইনটি stdinশেল ভেরিয়েবলে পড়ে $l। এটি প্রয়োজনীয় কারণ while head </dev/null; do :; doneঅনির্দিষ্টকালের জন্য পুনরাবৃত্তি হবে - headএটি ফাইলের শেষের দিকে পৌঁছলে তার ফিরতিতে নির্দেশ করে। সুতরাং ইওএফের বিরুদ্ধে চেকটি উত্সর্গীকৃত readএবং কেবলমাত্র দ্বিতীয় তর্কটি ধনাত্মক পূর্ণসংখ্য হলে কেবল একটি নতুন লাইন printfলিখবে ।$lstdout

readচেক লুপ একটু complicates কারণ অবিলম্বে পরে অন্য লুপ বলা হয় - একটি forলুপ যা args উপর iterates 2-$#মধ্যে প্রতিনিধিত্ব হিসাবে $nতার পিতা বা মাতা প্রতিটি পুনরাবৃত্তির জন্য whileলুপ। এর অর্থ হ'ল প্রতিটি পুনরাবৃত্তির জন্য কমান্ড লাইনে নির্দিষ্ট মান থেকে প্রথম আরগটি হ্রাস করতে হবে, তবে অন্য সকলকে তাদের মূল মানগুলি ধরে রাখতে হবে, এবং তাই $_nচিহ্নিতকারী ভারের মান প্রতিটি থেকে বিয়োগ করা হয়, তবে কেবল কখনও ধরে রাখে প্রথম আর্গের জন্য 0 এর চেয়ে বড় মান।

এটি ফাংশনের মূল লুপটি গঠন করে, তবে কোডের বেশিরভাগ অংশ শীর্ষে থাকে এবং এটি ফাংশনটিকে পরিষ্কারভাবে ইনপুট হিসাবে একটি পাইপ এমনকি বাফার করতে সক্ষম করার উদ্দেশ্যে is এটি প্রথমে ব্যাকগ্রাউন্ডে কল করে কাজ করে এটি dd4 টুকরো টুকরো এর ব্লক আকারে আউটপুটটিতে একটি টেম্পফাইলে অনুলিপি করতে। ফাংশনটি এরপরে একটি হোল্ড লুপ সেট আপ করে - যা প্রায় কোনও একক সম্পূর্ণ চক্রও শেষ করা উচিত নয় - কেবলমাত্র এটি নিশ্চিত করার জন্য যে ddফাংশনের আগে ফাইলটিতে কমপক্ষে একটি লিখিত রচনা তৈরি হয়েছে তারপরে তার স্টিডিনকে টেম্পফিলের সাথে যুক্ত ফাইল বর্ণনাকারীর সাথে প্রতিস্থাপন করবে এবং এরপরে তত্ক্ষণাত্ ফাইলটি লিঙ্কযুক্ত করেrm। এটি ফাংশনটি ফাঁদগুলির প্রয়োজনীয়তা ছাড়াই বা অন্যথায় ক্লিনআপের জন্য প্রবাহকে নির্ভরযোগ্যভাবে প্রক্রিয়াজাত করতে সক্ষম করে - fd এ দাবি করা ফাংশনটি প্রকাশের সাথে সাথেই টেম্পফাইলটি বন্ধ হয়ে যাবে কারণ এর নামকরণ করা ফাইলসিস্টেম লিঙ্কটি ইতিমধ্যে সরানো হয়েছে।


0

এর মতো ব্যাশ ফাংশন ব্যবহার করুন:

seq 1 30 > input.txt
f(){ head $1 input.txt | tail $2 >> output.txt ;}; f -11 -2; f -24 -3
cat output.txt
10
11
22
23
24

এই ক্ষেত্রে এটি কিছুটা ওভারকিল, তবে যদি আপনার ফিল্টারগুলি আরও বড় হয় তবে এটি কোনও वर হয়ে উঠতে পারে।

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