সম্পূর্ণ স্টিডিনে স্টিডিনের শেষ লাইনটি প্রস্তুত করুন


9

এই স্ক্রিপ্ট বিবেচনা করুন:

tmpfile=$(mktemp)

cat <<EOS > "$tmpfile"
line 1
line 2
line 3
EOS

cat <(tail -1 "$tmpfile") "$tmpfile"

এটি কাজ করে এবং ফলাফলগুলি:

line 3
line 1
line 2
line 3

আসুন আমরা বলি যে আমাদের ইনপুট উত্স, প্রকৃত ফাইল হওয়ার পরিবর্তে স্টিডিন ছিল:

cat <<EOS | # what goes here now?
line 1
line 2
line 3
EOS

আমরা কীভাবে আদেশটি পরিবর্তন করব:

cat <(tail -1 "$tmpfile") "$tmpfile"

যাতে এটি এখনও একই আউটপুট উত্পাদন করে, এই ভিন্ন প্রসঙ্গে?

দ্রষ্টব্য: আমি যে নির্দিষ্ট হেরেডোককে ক্যাট করছি তা হ'ল হেরডোক নিজেই ব্যবহার নিছক বর্ণনামূলক। যে কোনও গ্রহণযোগ্য উত্তরের ধারনা করা উচিত যে এটি স্টিডিনের মাধ্যমে স্বেচ্ছাসেবী তথ্য গ্রহণ করছে


1
stdin সর্বদা একটি "আসল ফাইল" (একটি ফিফো / সকেট / ইত্যাদি একটি ফাইলও; সমস্ত ফাইল অনুসন্ধানযোগ্য নয়)। আপনার প্রশ্নের উত্তর হ'ল হয় একটি তুচ্ছ "অস্থায়ী ফাইল ব্যবহার করুন" বা কোনও হরর যা মেমরিতে পুরো ফাইলটি লোড করবে। "আমি কোনও প্রবাহ সংরক্ষণ না করে কীভাবে কোনও প্রবাহ থেকে পুরানো ডেটা পুনরুদ্ধার করতে পারি ?" একটি ভাল উত্তর থাকতে পারে না।
ম্যাসভি

1
@ মোসভি আপনি এটি যুক্ত করতে চাইলে এটি একটি নিখুঁত গ্রহণযোগ্য উত্তর।
জোনাহ

2
@ মোসভি যেমন জোনা বলেছেন, উত্তরগুলি উত্তর বক্সে পোস্ট করা উচিত। আমি জানি যে এই মুহুর্তে ওয়েবসাইটের যে কোনওটি পড়তে মুশকিল, তবে দয়া করে সেই লালটিকে উপেক্ষা করুন যা ধীরে ধীরে আপনার দৃষ্টি থেকে সরে যাচ্ছে এবং নীচের পাঠ্যটি ব্যবহার করুন।
wizzwizz4

উত্তর:


7

চেষ্টা করুন:

awk '{x=x $0 ORS}; END{printf "%s", $0 ORS x}'

উদাহরণ

আমাদের ইনপুট সহ একটি ভেরিয়েবল সংজ্ঞা দিন:

$ input="line 1
> line 2
> line 3"

আমাদের কমান্ড চালান:

$ echo "$input" | awk '{x=x $0 ORS}; END{printf "%s", $0 ORS x}'
line 3
line 1
line 2
line 3

বিকল্পভাবে, অবশ্যই, আমরা এখানে-ডক ব্যবহার করতে পারি:

$ cat <<EOS | awk '{x=x $0 ORS}; END{printf "%s", $0 ORS x}'
line 1
line 2
line 3
EOS
line 3
line 1
line 2
line 3

কিভাবে এটা কাজ করে

  • x=x $0 ORS

    এটি ভেরিয়েবলের প্রতিটি লাইন ইনপুট যুক্ত করে x

    Awk সালে ORSহয় আউটপুট রেকর্ড বিভাজক । ডিফল্টরূপে এটি একটি নতুন লাইনের চরিত্র।

  • END{printf "%s", $0 ORS x}

    আমরা পুরো ফাইলটি পড়ার পরে, এটি শেষ লাইনটি মুদ্রণ করে $0, তারপরে পুরো ফাইলের বিষয়বস্তু অনুসরণ করে x

যেহেতু এটি পুরো ইনপুটটিকে মেমরির মধ্যে পড়ে, তাই এটি বৃহত ( যেমন গিগাবাইট) ইনপুটগুলির পক্ষে উপযুক্ত হবে না ।


ধন্যবাদ জন। সুতরাং ওপিতে আমার নামযুক্ত ফাইলের উদাহরণের সাথে সাদৃশ্যপূর্ণভাবে এটি করা কি সম্ভব নয়? আমি স্ট্যান্ডিনটিকে কোনওভাবে নকল করা হয়েছিল বলে কল্পনা করছিলাম ... এইভাবে সাজানোর উপায় teeআছে, তবে একটি স্টিডিন এবং একটি ফাইল, আমরা একই স্টিডিনকে দুটি পৃথক প্রক্রিয়া বিকল্পে পাইপ করব। বা কিছু যে মোটামুটি যে সমান হবে?
জোনা

5

যদি স্টিডিন কোনও সন্ধানযোগ্য ফাইলের দিকে নির্দেশ করে (যেমন বাশের (তবে অন্যান্য সমস্ত শেলের নয়) এখানে টেম্প ফাইলগুলির সাথে প্রয়োগ করা হয় এমন নথি), আপনি পুচ্ছটি পেতে পারেন এবং তারপরে সম্পূর্ণ সামগ্রীগুলি পড়ার আগে ফিরে যেতে পারেন:

চাইতে অপারেটার পাওয়া যায় zshবা ksh93শাঁস বা TCL / Perl / পাইথন, কিন্তু না মত স্ক্রিপ্টিং ভাষার bash। আপনার যদি ব্যবহার করতে হয় তবে আপনি সর্বদা সেই আরও উন্নত দোভাষীকে কল bashকরতে পারেন bash

ksh93 -c 'tail -n1; cat <#((0))' <<...

অথবা

zsh -c 'zmodload zsh/system; tail -n1; sysseek 0; cat' <<...

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

স্মৃতিতে সঞ্চয় করার জন্য কিছু সমাধান ইতিমধ্যে দেওয়া হয়েছে।

একটি টেম্পাইল দিয়ে, এর সাথে zsh, আপনি এটি দিয়ে এটি করতে পারেন:

seq 10 | zsh -c '{ cat =(sed \$w/dev/fd/3); } 3>&1'

যদি লিনাক্সে, bashঅথবা zsh-র সাথে বা কোনও শেল যা এখানে-নথিগুলির জন্য টেম্প ফাইলগুলি ব্যবহার করে, আপনি আউটপুট সংরক্ষণের জন্য এখানে একটি ডকুমেন্টের দ্বারা তৈরি টেম্প ফাইলটি ব্যবহার করতে পারেন:

seq 10 | {
  chmod u+w /dev/fd/3 # only needed in bash5+
  cat > /dev/fd/3
  tail -n1 /dev/fd/3
  cat <&3
} 3<<EOF
EOF

4
cat <<EOS | sed -ne '1{h;d;}' -e 'H;${G;p;}'
line 1
line 2
line 3
EOS

এটি ব্যবহার করে tailএমন কিছুতে এটি অনুবাদ করার সাথে সম্পর্কিত সমস্যাটি হ'ল tailএটির শেষ সন্ধানের জন্য পুরো ফাইলটি পড়তে হবে। আপনার পাইপলাইনে এটি ব্যবহার করতে, আপনার প্রয়োজন

  1. নথির সম্পূর্ণ সামগ্রী সরবরাহ করুন tail
  2. এটি আবার প্রদান cat
  3. সেই জন্য.

জটিল বিটটি নথির সামগ্রীতে নকল করা নয় ( teeএটি করে) তবে tailঅন্তর্বর্তী অস্থায়ী ফাইলটি ব্যবহার না করেই বাকী নথির আউটপুট আসার আগে আউটপুট ঘটবে।

sed(বা জন 1024awk যেমনটি ব্যবহার করা ) ব্যবহার করে ডেটা ডাবল পার্সিং এবং অর্ডারিং ইস্যু থেকে ডেটা মেমোরিতে সঞ্চয় করে মুক্তি পাওয়া যায়।

sedসমাধান আমি উত্থাপন করা হয়

  1. 1{h;d;}, হোল্ড স্পেসে প্রথম লাইনটি সংরক্ষণ করুন, যেমন রয়েছে, এবং পরবর্তী লাইনে যান।
  2. H, এম্বেড করা নতুনলাইন সহ একে অপরের লাইনটিকে হোল্ড স্পেসে যুক্ত করুন।
  3. ${G;p;}এম্বেড করা নতুন লাইনের সাহায্যে হোল্ড স্পেসটি শেষ লাইনে যুক্ত করুন এবং ফলাফলটি মুদ্রণ করুন।

এটি জন1024 এর সমাধানটির পুরো আক্ষরিক অনুবাদ sed, এই সাবধানতার সাথে যে পসিএক্স স্ট্যান্ডার্ডটি কেবল গ্যারান্টি দেয় যে হোল্ড স্পেসটি কমপক্ষে 8192 বাইট (8 কিবি;) রয়েছে তবে এটি সুপারিশ করে যে এই বাফারটি গতিশীলভাবে বরাদ্দ করা হয়েছে এবং প্রয়োজনীয় হিসাবে প্রসারিত করা হয়েছে, যা উভয়ই জিএনইউ করেছে sedএবং বিএসডি sedকরছে)


যদি আপনি নিজেকে একটি নামক পাইপ ব্যবহার করার অনুমতি দেন:

mkfifo mypipe
cat <<EOS | tee mypipe | cat <( tail -n 1 mypipe ) -
line 1
line 2
line 3
EOS
rm -f mypipe

এটি teeডেটা নিচে mypipeএবং একই সাথে প্রেরণে ব্যবহার করে catcatউপযোগ প্রথম থেকে আউটপুট পড়তে হবে tail(যা থেকে সার্চ mypipe, যা teeলেখা হয়), এবং তারপর দস্তাবেজ থেকে সরাসরি আসছে কপি সংযোজন tee

সেখানে যে যদি নথি এই যদিও একটি গুরুতর ত্রুটি আছে, অত্যন্ত বড় (নল এর বাফারের আকার চেয়ে বড়), teeথেকে এর লেখা mypipeএবং catযখন (নামবিহীন) পাইপ খালি জন্য অপেক্ষা ব্লক হবে। এটি catথেকে পড়া না হওয়া পর্যন্ত খালি করা হবে না । catশেষ না হওয়া পর্যন্ত এটি থেকে পড়া হবে না tail। এবং tailশেষ না হওয়া পর্যন্ত শেষ হবে না tee। এটি একটি ক্লাসিক অচলাবস্থার পরিস্থিতি।

তারতম্য

tee >( tail -n 1 >mypipe ) | cat mypipe -

একই সমস্যা আছে।


2
sedযদি ইনপুট শুধুমাত্র একটি লাইন (হয়তো একটিই কাজ করে না sed '1h;1!H;$!d;G')। এছাড়াও নোট করুন যে কয়েকটি sedবাস্তবায়নের তাদের প্যাটার্ন এবং হোল্ড স্পেসের আকারের কম সীমা রয়েছে।
স্টাফেন চেজেলাস

নামযুক্ত পাইপ সমাধানটি আমি যে ধরণের জিনিসটি খুঁজছিলাম is সীমাবদ্ধতা লজ্জাজনক। আমি "এবং টি শেষ না হওয়া পর্যন্ত লেজ শেষ হবে না" ব্যতীত আপনার ব্যাখ্যাটি আমি বুঝতে পেরেছি - কেন আপনি কেন বিষয়টি ব্যাখ্যা করতে পারেন?
জোনা

2

peeকমান্ড-লাইন ইউটিলিটিগুলির সংকলনে একটি সরঞ্জাম রয়েছে যার নামটি সাধারণত "মোরটিলস" (বা অন্যথায় তার হোম ওয়েবসাইট থেকে পুনরুদ্ধারযোগ্য ) নামে প্যাকেজ করা থাকে ।

আপনি যদি এটি আপনার সিস্টেমে রাখতে পারেন তবে আপনার উদাহরণের সমতুল্য হ'ল:

cat <<EOS | pee 'tail -1' cat 
line 1
line 2
line 3
EOS

কমান্ডগুলির মাধ্যমে পরিচালিত আদেশগুলি peeগুরুত্বপূর্ণ কারণ তারা প্রদত্ত ক্রমটিতে কার্যকর করা হয়।


1

চেষ্টা করুন:

cat <<EOS # | what goes here now? Nothing!
line 3
line 1
line 2
line 3
EOS

যেহেতু পুরো জিনিসটি আক্ষরিক ডেটা (একটি "এখানে ডকুমেন্ট"), এবং এটির মধ্যে এবং কাঙ্ক্ষিত আউটপুটটি তুচ্ছ, তাই আউটপুটটির সাথে ম্যাচ করার জন্য ঠিক সেই আক্ষরিক ডেটা ম্যাসেজ করুন।

এখন ধরা যাক line 3কোথাও থেকে এসেছে এবং এটি একটি ভেরিয়েবলে সংরক্ষণ করা হয়েছে lastline:

cat <<EOS # | what goes here now? Nothing!
$lastline
line 1
line 2
$lastline
EOS

এখানে একটি ডকটিতে, আমরা ভেরিয়েবলগুলি স্থির করে পাঠ্য উত্পন্ন করতে পারি। কেবল এটিই নয় আমরা কমান্ড প্রতিস্থাপন ব্যবহার করে পাঠ্য গণনা করতে পারি:

cat <<EOS
this is template text
here we have a hex conversion: $(printf "%x" 42)
EOS

আমরা একাধিক লাইন বিভক্ত করতে পারি:

cat <<EOS
multi line
preamble
$(for x in 3 1 2 3; do echo line $x ; done)
epilog
EOS

সাধারণভাবে, এখানে ডক টেমপ্লেট পাঠ্য প্রক্রিয়াকরণ এড়ান; ইন্টারপোলটেড কোড ব্যবহার করে এটি উত্পন্ন করার চেষ্টা করুন।


1
আমি সত্যিই বলতে পারি না এটি রসিকতা আছে কি না। cat <<EOS...ওপি মধ্যে শুধু "একটি অবাধ ফাইল catting," পোস্ট নির্দিষ্ট এবং প্রশ্ন পরিষ্কার বর্ণনা করে দেন একটি উদাহরণ standin ছিল। এটি কি আপনার কাছে প্রকৃতই স্পষ্ট ছিল না, বা আপনি কি মনে করেছিলেন যে প্রশ্নটির আক্ষরিক ব্যাখ্যা করা চতুর হবে?
জোনা

@ জোনাঃ প্রশ্নটি পরিষ্কারভাবে বলেছে "[এল] এট এর বলছেন যে আমাদের ইনপুট উত্স, প্রকৃত ফাইল হওয়ার পরিবর্তে পরিবর্তে স্টিডিন ছিল:"। "স্বেচ্ছাসেবী ফাইল" সম্পর্কে কিছুই নয়; এটি এখানে ডক্স সম্পর্কে। এখানে একটি ডক স্বেচ্ছাসেবক নয়। এটি আপনার প্রোগ্রামের একটি ইনপুট নয়, তবে প্রোগ্রামারটি চয়ন করে এমন একটি সিনট্যাক্সের টুকরো।
কাজ

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

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

1
কাজ, ইনপুটটি কেবল উদাহরণ হিসাবে রয়েছে। আমাকে সহ বেশিরভাগ লোকেরা কেবল বিমূর্ত প্রশ্নটি না করে সত্যিকারের ইনপুট এবং প্রত্যাশিত আউটপুটটির উদাহরণ পাওয়া সহায়ক বলে মনে করেন। আপনি কেবল সেই ব্যক্তি যিনি এতে বিভ্রান্ত হয়েছিলেন।
জোনাহ

0

আপনি যদি অর্ডার সম্পর্কে চিন্তা না করেন। তাহলে এই কাজ করবে cat lines | tee >(tail -1)। যেমনটি অন্যরা বলেছেন। আপনার দু'বার ফাইল পড়তে হবে বা পুরো ফাইলটি বাফার করতে হবে, আপনার অনুরোধ অনুসারে করতে in

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