কীভাবে কেবল শেষ কলামটি মুদ্রণ করবেন?


25
echo -e 'one two three\nfour five six\nseven eight nine'
one two three
four five six
seven eight nine

এই আউটপুটটি পেতে আমি কীভাবে কিছু "ম্যাজিক" করতে পারি ?:

three
six
nine

আপডেট: এই নির্দিষ্ট উপায়ে আমার এটির দরকার নেই, আমার একটি সাধারণ সমাধান প্রয়োজন যাতে এককভাবে যতগুলি কলামই না হয়, যেমন: awk সর্বদা শেষ কলামটি প্রদর্শন করে।


2
ল্যানস জিজ্ঞাসার আগে আপনার প্রশ্নগুলি গবেষণা করুন। আপনার পোস্টের সাবজেক্ট লাইনের জন্য গুগল অনুসন্ধান করা স্নিপেন্টদের উত্তর দেখায়। "Awk সর্বশেষ কলাম" অনুসন্ধান করা ফলাফল 1 এর সাথে শুরু করে বেশ কয়েকটি দুর্দান্ত উত্তর দেয় Also এছাড়াও, 5 মিনিটের এই অ্যাজক প্রাইমারটি পুরোপুরিই পড়ার পক্ষে মূল্যবান যাতে আপনি জানেন যে ভবিষ্যতে কী সম্ভব।
কালেব

উত্তর:


6

এটি এমনকি শুধুমাত্র সঙ্গে সম্পন্ন করা যাবে 'bash'ছাড়া 'sed', 'awk'অথবা 'perl':

echo -e 'one two three\nfour five six\nseven eight nine' |
  while IFS=" " read -r -a line; do
    nb=${#line[@]}
    echo ${line[$((nb - 1))]}
  done

হুম, বা এটিও ধরে নেওয়া, আপনার ইনপুটটি আসলে স্থান-পৃথক:... | while read -r line; do echo ${line##* }; done
গ্লেন জ্যাকম্যান

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

2
bashঅ্যারে সূচক গাণিতিক মূল্যায়নের বিষয়, তাই echo ${line[nb - 1]}যথেষ্ট। হিসাবে কথা bash, আপনি শুধু এড়িয়ে যেতে পারেন "বিশেষ দ্রষ্টব্য" জিনিস: echo ${line[-1]}। পরে একটি আরো পোর্টেবল বিকল্প: echo ${line[@]: -1]}। ( অন্য কোথাও নেতিবাচক সূচকে স্টিফেন চেজেলাসের মন্তব্য দেখুন ))
মানটওয়ার্ক

53

চেষ্টা করুন:

echo -e 'one two three\nfour five six\nseven eight nine' | awk '{print $NF}'


দয়া করে মনে রাখবেন যে বিশ্রী 99 টি ক্ষেত্রের মধ্যে সীমাবদ্ধ ...: / এটি কেবল আমাকে গত দিনগুলিতে কামড়ায় ফেলেছিল ( ps -ef | awk '{ print $NF }'কিছু লাইন কেটে গেছে ...) পার্লের এই সীমাবদ্ধতা নেই। ( gnu.org/software/autoconf/manual/autoconf-2.67/html_node/… : "ট্র্যাডিশনাল আওকের একটি রেকর্ডে 99 টি ক্ষেত্রের সীমা রয়েছে T ট্রু 64 এর মতো কিছু অ্যাওক বাস্তবায়ন, আপনি উল্লেখ না করলেও ইনপুট বিভক্ত করুন স্ক্রিপ্টের যে কোনও ক্ষেত্রে, এই সমস্যাটি থেকে মুক্তি পেতে একটি অস্বাভাবিক চরিত্রের জন্য 'FS' সেট করুন এবং বিভাজনটি ব্যবহার করুন))
অলিভিয়ার ডুলাক

@ অলিভিয়ারডুলাক কী awkবাস্তবায়নের সেই সীমাবদ্ধতা রয়েছে? আমি কখনই দেখিনি। আমার mawkদম বন্ধ হবে 32768কিন্তু আমার gawkএবং igawkলক্ষ লক্ষগুলির সাথে সুখে ডিল করতে পারে। এমনকি আমার ব্যস্তবক্সও awkকয়েক মিলিয়ন ডিল করতে পারে। আমি কখনই এমনটি পারিনি awkযা 100 ক্ষেত্রের সাথে ডিল করতে পারে না, এটি একটি ক্ষুদ্র সংখ্যা, সর্বোপরি। আপনি কি নিশ্চিত যে তথ্যটি এখনও প্রাসঙ্গিক? এমনকি সোলারিসেও?
টেরডন

@ ইটারডন, আমার মন্তব্যে লিঙ্কগুলি দেখুন ^^ (এবং বিশ্বাস করুন, কিছু "উত্তরাধিকারসূত্রে" সিস্টেম কিছু পরিবেশে লুওলোগ সময় বেঁচে থাকতে পারে some কিছু, তারে হাপিলি "/" তে এক্সট্র্যাক্ট করে, বাশের কিছু ব্যবহারযোগ্য নেই) বিল্টিনস (না $ BASH_SOURCE, উদাহরণস্বরূপ), এনএফ> ৯৯, ইত্যাদিতে অজানা দমবন্ধ ... :()
অলিভিয়ার ডুলাক

@ অলিভিয়ারডুলাক পর্যাপ্ত। আমি শুধু এটি পেরেছি না। আমি আশা করি যে এটি আজ বিরলভাবে বিরল, যেহেতু 99 একটি সংখ্যার সংখ্যক।
terdon

14

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

$ echo one two three | awk '{print $NF}'
three

11

চেষ্টা করুন grep( awkরেগেক্স ব্যবহারের কারণে খাটো / সরল, তবে 3x ধীর )

grep -o '\S\+$' <(echo -e '... seven eight nine')

অথবা ex(আরও ধীর গতিযুক্ত, তবে এটি সমাপ্তির পরে পুরো বাফারটি প্রিন্ট করে, যখন এটি জায়গায় বাছাই বা সম্পাদনা করা দরকার তখন আরও কার্যকর):

ex -s +'%s/^.*\s//g' -c'%p|q!' <(echo -e '... seven eight nine')
ex +'%norm $Bd0' -sc'%p|q!' infile

ইন-জায়গা পরিবর্তন করতে, প্রতিস্থাপন -sc'%p|q!'সঙ্গে -scwq

বা bash:

while read line; do arr=($line); echo ${arr[-1]}; done < someinput

কর্মক্ষমতা

এর মাধ্যমে উত্পন্ন 1GB ফাইল দেওয়া হয়েছে:

$ hexdump -C /dev/urandom | rev | head -c1G | pv > datafile

আমি বিশ্লেষণের সময় পরিসংখ্যান সম্পাদন করেছি (এমবিপি ওএস এক্স-তে পরীক্ষিত সর্বনিম্ন ~ 3x এবং সর্বনিম্ন নিয়েছি):

  • ব্যবহার awk:

    $ time awk '{print $NF}' datafile > /dev/null
    real    0m12.124s
    user    0m10.704s
    sys 0m0.709s
  • ব্যবহার grep:

    $ time grep -o '\S\+$' datafile > /dev/null
    real    0m36.731s
    user    0m36.244s
    sys 0m0.401s
    
    $ time grep -o '\S*$' datafile > /dev/null
    real    0m40.865s
    user    0m39.756s
    sys 0m0.415s
  • ব্যবহার perl:

    $ time perl -lane 'print $F[-1]' datafile > /dev/null
    real    0m48.292s
    user    0m47.601s
    sys 0m0.396s
  • ব্যবহার rev+ + cut:

    $ time (rev|cut -d' ' -f1|rev) < datafile > /dev/null
    $ time rev datafile | cut -d' ' -f1 | rev > /dev/null
    real    1m10.342s
    user    1m19.940s
    sys 0m1.263s
  • ব্যবহার ex:

    $ time ex +'%norm $Bd0_' -sc'%p|q!' datafile > /dev/null
    real    3m47.332s
    user    3m42.037s
    sys 0m2.617s
    $ time ex +'%norm $Bd0' -sc'%p|q!' datafile > /dev/null
    real    4m1.527s
    user    3m44.219s
    sys 0m6.164s
    $ time ex +'%s/^.*\s//g' -sc'%p|q!' datafile > /dev/null
    real    4m16.717s
    user    4m5.334s
    sys 0m5.076s
  • ব্যবহার bash:

    $ time while read line; do arr=($line); echo ${arr[-1]}; done < datafile > /dev/null
    real    9m42.807s
    user    8m12.553s
    sys 1m1.955s

6
... | perl -lane 'print $F[-1]'

মূল বিষয় -a:, @Fঅ্যারেতে অটোস্প্লিট ক্ষেত্র ; -lchops বন্ধ $/(ইনপুট রেকর্ড বিভাজক) এবং এটি সংরক্ষণ করে $\(আউটপুট রেকর্ড বিভাজক)। যেহেতু কোনও অষ্টাল নম্বর সরবরাহ করা হয়নি -l, মূল $/মুদ্রণটিতে প্রয়োগ করা হয় (লাইন শেষ); -nলুপ কোড; -eএরপরেই কোড কার্যকর করুন exec দেখুন man perlrun
জনাথন কোমার

5

এটি ব্যবহার করেও করা যেতে পারে 'sed':

echo -e 'one two three\nfour five six\nseven eight nine' | sed -e 's/^.* \([^ ]*\)$/\1/'

হালনাগাদ:

বা আরও সহজভাবে:

echo -e 'one two three\nfour five six\nseven eight nine' | sed -e 's/^.* //'

আরও সহজ আরও ভাল!
এমডিপিসি

@ এমডিপিসি: আমি সম্মত, তবে আরও জটিল সমাধান ইতিমধ্যে পোস্ট করার কারণে, আমি এটি রাখার সিদ্ধান্ত নিয়েছি।
jfg956

5

বা ব্যবহার cut:

echo -e 'one two three\nfour five six\nseven eight nine' | cut -f 3 -d' '

যদিও এটি 'সাধারণ সমাধান' প্রয়োজনীয়তা পূরণ করে না। revদু'বার ব্যবহার করে আমরা এর সমাধানও করতে পারি:

echo -e 'one two three\nfour five six\nseven eight nine' | rev | cut -f 1 -d' ' | rev

আমি মনে করি না যে 'রেভ' সমস্ত ইউনিক্সে (এআইএক্স, সোলারিস, ...) পাওয়া যাবে বা সমস্ত লিনাক্সে ইনস্টল করা আছে তবে চমৎকার বিকল্প সমাধান রয়েছে।
jfg956

1
ডাবল রেভের জন্য +1, তবে পার্শ্ব নোট হিসাবে, rev'বিস্তৃত' অক্ষরগুলির সাথে কাজ করে না, কেবলমাত্র একক বাইটগুলি, যতদূর আমি জানি।
মার্সিন

2

awkআপনি ব্যবহার করে প্রথমে কমপক্ষে একটি কলাম আছে কিনা তা পরীক্ষা করতে পারেন।

echo | awk '{if (NF >= 1) print $NF}'

echo 1 2 3 | awk '{if (NF >= 1) print $NF}'

3
বা কম verbosely awk 'NF{print $NF}'
manatwork

1

পার্লে এটি নিম্নলিখিত হিসাবে করা যেতে পারে:

#!/usr/bin/perl

#create a line of arbitrary data
$line = "1 2 3 4 5";

# splt the line into an array (we call the array 'array', for lolz)
@array = split(' ', $line);

# print the last element in the array, followed by a newline character;
print "$array[-1]\n";

আউটপুট:

$ perl last.pl
5
$

আপনি কোনও ফাইলের মধ্য দিয়ে লুপও করতে পারেন, বাজেট.ড্যাট নামক কোনও ফাইলকে পার্স করার জন্য আমি লিখেছি এমন একটি উদাহরণ স্ক্রিপ্ট

বাজেটে ডেটা উদাহরণ.ড্যাট:

Rent              500
Food              250
Car               300
Tax               100
Car Tax           120
Mag Subscription  15

(আপনি দেখতে পাচ্ছেন যে আমার কেবল "শেষ" কলামটি ক্যাপচার করা দরকার, কেবল কলাম 2 নয়)

এই পান্ডুলিপি:

#!/usr/bin/perl
$budgetfile = "budget.dat";
open($bf, $budgetfile)
        or die "Could not open filename: $filename $!";


print "-" x 50, "\n";
while ( $row = <$bf> ) {
        chomp $row;
        @r = split (' ', $row);
        print "$row ";
        $subtotal += $r[-1];
        print "\t$subtotal\n";
}
print "-" x 50, "\n";
print "\t\t\t Total:\t$subtotal\n\n";

আমি বুঝতে পেরেছি যে অন্য কেউ এরই মধ্যে একই মন্তব্য করেছেন, এ সম্পর্কে দুঃখিত, কমপক্ষে আমার কাছে কয়েকটি উদাহরণও রয়েছে, আশা করি এটি যেভাবেই আলোচনায় যুক্ত হবে।
urbansumo
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.