আমি কীভাবে লুপের জন্য বিপরীত করব?


26

আমি কীভাবে বিপরীত ক্রমে লুপটি সঠিকভাবে করব for?

for f in /var/logs/foo*.log; do
    bar "$f"
done

আমার এমন একটি সমাধান দরকার যা ফাইলের নামগুলিতে ভীতু চরিত্রগুলির জন্য ভেঙে না যায়।


5
কেবল sort -rআগে পাইপ করুন forবা এর মধ্য দিয়ে লন্ডার করুন ls -r
ডেভিড শোয়ার্জ

উত্তর:


27

বাশ বা কেএস-তে, ফাইলের নামগুলি একটি অ্যারেতে রাখুন এবং সেই অ্যারের উপরে বিপরীত ক্রমে পুনরাবৃত্তি করুন।

files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
  bar "${files[$i]}"
done

ksh_arraysবিকল্পটি সেট করা থাকলে উপরের কোডটিও zsh এ কাজ করে (এটি ksh এমুলেশন মোডে রয়েছে)। জেডএসে একটি সহজ পদ্ধতি রয়েছে, যা গ্লোব কোয়ালিফায়ারের মাধ্যমে ম্যাচের ক্রমটি বিপরীত করা:

for f in /var/logs/foo*.log(On); do bar $f; done

পসিক্স অ্যারেগুলিকে অন্তর্ভুক্ত করে না, সুতরাং আপনি যদি পোর্টেবল হতে চান তবে আপনার স্ট্রিংগুলির একটি অ্যারে সরাসরি সঞ্চয় করার বিকল্পটি অবস্থানগত পরামিতি।

set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
  eval "f=\${$i}"
  bar "$f"
  i=$((i-1))
done

একবার আপনি অবস্থানগত পরামিতি ব্যবহার করার পরে, আপনার ভেরিয়েবলগুলির প্রয়োজন নেই iএবং f; কেবলমাত্র একটি সম্পাদন করুন shift, $1আপনার কলটি ব্যবহার barকরুন [ -z $1 ]এবং আপনার মধ্যে পরীক্ষা করুন while
ব্যবহারকারী1404316

@ ব্যবহারকারী1404316 এটি উপাদানগুলির উপর আরোহণের ক্রমে ক্রমবর্ধমান জটিল পদ্ধতি হবে । এছাড়াও, ভুল: তন্ন তন্ন [ -z $1 ]না [ -z "$1" ]দরকারী পরীক্ষা হয় (যদি প্যারামিটার ছিল *, অথবা একটি খালি স্ট্রিং?)। এবং যে কোনও ক্ষেত্রে তারা এখানে সহায়তা করে না: বিপরীত ক্রমে কীভাবে লুপ করবেন তা প্রশ্ন।
গিলস 'অশুভ হওয়া বন্ধ করুন'

প্রশ্নটি সুনির্দিষ্টভাবে বলেছে যে এটি / var / লগের মধ্যে ফাইলের নামগুলি নিয়ে পুনরাবৃত্তি করছে, সুতরাং এটি ধরে নেওয়া নিরাপদ যে কোনও পরামিতি "*" বা খালি হবে না। আমি বিপরীত ক্রমের পয়েন্টে, সংশোধন করি না।
ব্যবহারকারী1404316

7

আপনি চেষ্টা করুন যদি না আপনি লাইন ব্রেককে "ফানকি চরিত্র" হিসাবে বিবেচনা করেন:

ls /var/logs/foo*.log | tac | while read f; do
    bar "$f"
done

লাইন ব্রেক নিয়ে কাজ করে এমন কোন পদ্ধতি আছে কি? (আমি জানি এটি বিরল, তবে কমপক্ষে শেখার স্বার্থে আমি সঠিক কোডটি লেখা সম্ভব কিনা তা জানতে চাই))
মেহেরদাবাদ

স্রোতের বিপরীতে ট্যাক ব্যবহার করার জন্য সৃজনশীল, এবং আপনি যদি কিছু অযাচিত অক্ষরগুলি যেমন লাইন ব্রেকগুলির থেকে মুক্তি পেতে চান তবে আপনি ট্র-ডি '\ n' এ পাইপ করতে পারেন।
জোহান

4
যদি ফাইলের নামগুলিতে নিউলাইনস, ব্যাকস্ল্যাশস বা অপ্রিন্টযোগ্য অক্ষর থাকে তবে এটি ব্রেক হয়। Mywiki.wooledge.org/ParsingLs দেখুন এবং কোনও ফাইলের লাইনটি কীভাবে লুপ করবেন? (এবং লিঙ্কযুক্ত থ্রেড)।
গিলস 'অশুভ হওয়া বন্ধ করুন'

সর্বাধিক ভোট দেওয়া উত্তর fআমার পরিস্থিতিতে পরিবর্তনশীলকে ভেঙে দিয়েছে । এই উত্তরটি যদিও সাধারণ forলাইনের জন্য একটি ড্রপ-ইন প্রতিস্থাপন হিসাবে বেশ কার্যকরভাবে কাজ করে ।
সার্জ Stroobandt

2

যদি কেউ কোনও স্থান-বিস্মৃত স্ট্রিং তালিকার উপরে কীভাবে পুনরাবৃত্তি করতে হয় তা নির্ধারণের চেষ্টা করছেন, এটি কাজ করে:

reverse() {
  tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}

list="a bb ccc"

for i in `reverse $list`; do
  echo "$i"
done
> ccc
> bb 
> a

2
আমার সিস্টেমে ট্যাক নেই; আমি জানি না এটি শক্তিশালী কিনা তবে আমি x এর জন্য $ {mylist} ব্যবহার করছিলাম; do revv = "$ {x} $ {revv}"; কাজ
Arp

@ আরপি tacজিএনইউ কোর্টিলসের অংশ হিসাবে এটি ধরণের ধাক্কা ocking তবে আপনার সমাধানটিও ভাল।
ACK_stoverflow

@ACK_stoverflow লিনাক্স ব্যবহারকারীল্যান্ড সরঞ্জাম ছাড়া সিস্টেম রয়েছে।
কুসালানন্দ

@ কুসালানন্দ আপনি কি বলছেন যে কেবল লিনাক্সই জিএনইউ কোর্টিল ব্যবহার করে? হাঃ হাঃ হাঃ. এমনকি ব্যস্তবক্সও আছে tac। যদিও tacএখানে অবিরাম প্রতিক্রিয়াগুলির সংখ্যা থেকে আমি অনুমান করি যে সম্ভবত ওএসএক্সের কাছে ট্যাক নেই। এই ক্ষেত্রে @ আরপের সমাধানের কিছু বৈকল্পিক ব্যবহার করুন - যাইহোক এটি বোঝা সহজ।
এসিকে_স্টোরফ্লো

হ্যাঁ, আমি এটিই বলছি
কুসালানন্দ

1
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar

আপনি যেভাবে চান সেটি পরিচালনা করা উচিত (এটি ম্যাক ওএস এক্সে পরীক্ষা করা হয়েছিল এবং আমার নীচে একটি সতর্কীকরণ রয়েছে ...)।

সন্ধানের জন্য ম্যান পৃষ্ঠা থেকে:

-print0
         This primary always evaluates to true.  It prints the pathname of the current file to standard output, followed by an ASCII NUL character (charac-
         ter code 0).

মূলত, আপনি সেই ফাইলগুলি সন্ধান করছেন যা আপনার স্ট্রিং + গ্লোব এর সাথে মেলে এবং প্রতিটি এনওএল চরিত্রের সাথে শেষ করে। যদি আপনার ফাইলের নামগুলিতে নিউলাইনস বা অন্যান্য অদ্ভুত অক্ষর থাকে তবে এটি ভালভাবে পরিচালনা করা উচিত find

tail -r

পাইপের মধ্য দিয়ে স্ট্যান্ডার্ড ইনপুট নেয় এবং এটির বিপরীত ঘটে (নোট করুন যে সমস্ত ইনপুট স্টাডাউটে tail -rপ্রিন্ট করে , এবং কেবল সর্বশেষ 10 লাইন নয়, এটিই স্ট্যান্ডার্ড ডিফল্ট more আরও তথ্যের জন্য)।man tail

আমরা তারপরে পাইপ দিন xargs -0:

-0      Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines.  This is expected to be used in concert with the
         -print0 function in find(1).

এখানে, xargs NUL অক্ষর দ্বারা বিভক্ত আর্গুমেন্টগুলি দেখতে প্রত্যাশা করে, যা আপনি পাশ থেকে findবিপরীত করেছেন tail

আমার সতর্কতা: আমি পড়েছি যে tailনাল-সমাপ্ত স্ট্রিংগুলির সাথে ভাল খেলছে না । এটি ম্যাক ওএস এক্সে ভাল কাজ করেছে, তবে আমি সমস্ত * নিক্সের ক্ষেত্রে এটির গ্যারান্টি দিতে পারি না। সাবধানে চলুন।

আমার আরও উল্লেখ করা উচিত যে GNU সমান্তরাল প্রায়শই xargsবিকল্প হিসাবে ব্যবহৃত হয় । আপনি এটিও পরীক্ষা করে দেখতে পারেন।

আমি কিছু অনুপস্থিত হতে পারে, তাই অন্যদের চিম্বই করা উচিত।


2
+1 দুর্দান্ত উত্তর। মনে হচ্ছে উবুন্টু tail -rযদিও সমর্থন করে না ... আমি কি কিছু ভুল করছি?
মেহরদাদ

1
না, আমি মনে করি না তুমি। আমার কাছে আমার লিনাক্স মেশিন আপ নেই তবে 'লিনাক্স টেল ম্যান' এর জন্য একটি দ্রুত গুগল এটিকে বিকল্প হিসাবে দেখায় না। সুনাকু tacবিকল্প হিসাবে উল্লেখ করেছেন, তাই আমি তার পরিবর্তে চেষ্টা করব
tcdyl

আমি আরও একটি বিকল্প অন্তর্ভুক্ত করার জন্য উত্তরটি সম্পাদনা করেছি
tcdyl

ওফস আমি +1 করতে ভুলে গিয়েছিলাম যখন আমি +1 বলেছিলাম :( হয়ে গেছে! সেই হা হা:) এর জন্য দুঃখিত :)
মেহেরদাবাদ

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

1

আপনার উদাহরণে আপনি বেশ কয়েকটি ফাইলের উপরে লুপিং করছেন তবে আমি আরও সাধারণ শিরোনামের কারণে এই প্রশ্নটি পেয়েছি যা কোনও অ্যারের উপরে লুপিংকে আবৃত করতে পারে বা কোনও সংখ্যার অর্ডারের ভিত্তিতে বিপরীত হতে পারে।

জেডশিতে এটি কীভাবে করা যায় তা এখানে:

আপনি যদি অ্যারেতে উপাদানগুলি লুপ করছেন তবে এই সিনট্যাক্সটি ( উত্স ) ব্যবহার করুন

for f in ${(Oa)your_array}; do
    ...
done

Oপরবর্তী পতাকাটিতে উল্লিখিত ক্রমের বিপরীতগুলি; aসাধারণ অ্যারে অর্ডার।

@ গিলিস যেমন বলেছিল, Onআপনার গ্লোববেড ফাইলগুলিকে বিপরীত করবে, যেমন my/file/glob/*(On)। এটি কারণ On"বিপরীত নাম ক্রম"।

Zsh বাছাই পতাকা:

  • a অ্যারের অর্ডার
  • L ফাইলের দৈর্ঘ্য
  • l লিঙ্ক সংখ্যা
  • m পরিবর্তন তারিখ
  • n নাম
  • ^oবিপরীত ক্রম ( oস্বাভাবিক ক্রম)
  • O বিপরীত ক্রম

উদাহরণস্বরূপ, https://github.com/grML/zsh-lovers/blob/master/zsh-lovers.1.txt এবং http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- দেখুন টু-মাস্টার-আপনার-Z-শেল /


0

ম্যাক ওএসএক্স tacআদেশটি সমর্থন করে না । @ টিসিডিএল দ্বারা সমাধানটি কাজ করে যখন আপনি forলুপে একটি একক কমান্ড কল করছেন । অন্যান্য সমস্ত ক্ষেত্রে, নীচে এটি কাছাকাছি যাওয়ার সহজ উপায়।

এই পদ্ধতির আপনার ফাইলের নামগুলিতে নতুন লাইন থাকা সমর্থন করে না। অন্তর্নিহিত কারণটি হ'ল, tail -rনতুন লাইনগুলি দ্বারা সীমিত হিসাবে এটি তার ইনপুটটি সাজায়।

for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done

তবে নতুন লাইনের সীমাবদ্ধতার আশেপাশে যাওয়ার একটি উপায় রয়েছে। যদি আপনি জানেন যে আপনার ফাইলের নামগুলিতে একটি নির্দিষ্ট অক্ষর নেই (বলুন, '='), তবে আপনি trএই চরিত্রটি হয়ে উঠতে সমস্ত নতুনলাইনগুলি প্রতিস্থাপন করতে ব্যবহার করতে পারেন এবং তারপরে বাছাই করতে পারেন। ফলাফলটি নিম্নলিখিত হিসাবে দেখাবে:

for i in `find [directory] -name '[filename]' -print0 | tr '\n' '=' | tr '\0' '\n'
| tail -r | tr '\n' '\0' | tr '=' '\n' | xargs -0`; do [commands]; done

দ্রষ্টব্য: আপনার সংস্করণটির উপর নির্ভর করে trএটি '\0'অক্ষর হিসাবে সমর্থন নাও করতে পারে । এটি স্থানীয়ভাবে সি-তে পরিবর্তিত করে প্রায় কাজ করা যেতে পারে (তবে আমি ঠিক কীভাবে মনে করতে পারি না, কারণ এটি ঠিক করার পরে এটি এখন আমার কম্পিউটারে একবার কাজ করে)। যদি আপনি একটি ত্রুটি বার্তা পেয়ে থাকেন এবং আপনি কাজের দিকটি খুঁজে না পান তবে দয়া করে এটি একটি মন্তব্য হিসাবে পোস্ট করুন, তাই আমি এটির সমস্যা সমাধানে আপনাকে সহায়তা করতে পারি।


0

ls -r@ ডেভিড শোয়ার্জ দ্বারা উল্লিখিত হিসাবে একটি সহজ উপায় ব্যবহার করা হয়

for f in $(ls -r /var/logs/foo*.log); do
    bar "$f"
done

-4

এটা চেষ্টা কর:

for f in /var/logs/foo*.log; do
bar "$f"
done

আমি মনে করি এটি সবচেয়ে সহজ উপায়।


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