বাশ কমান্ড আউটপুট থেকে একটি হিস্টোগ্রাম অঙ্কন


31

আমি নিম্নলিখিত আউটপুট আছে:

2015/1/7    8
2015/1/8    49
2015/1/9    40
2015/1/10   337
2015/1/11   11
2015/1/12   3
2015/1/13   9
2015/1/14   102
2015/1/15   62
2015/1/16   10
2015/1/17   30
2015/1/18   30
2015/1/19   1
2015/1/20   3
2015/1/21   23
2015/1/22   12
2015/1/24   6
2015/1/25   3
2015/1/27   2
2015/1/28   16
2015/1/29   1
2015/2/1    12
2015/2/2    2
2015/2/3    1
2015/2/4    10
2015/2/5    13
2015/2/6    2
2015/2/9    2
2015/2/10   25
2015/2/11   1
2015/2/12   6
2015/2/13   12
2015/2/14   2
2015/2/16   8
2015/2/17   8
2015/2/20   1
2015/2/23   1
2015/2/27   1
2015/3/2    3
2015/3/3    2

এবং আমি একটি হিস্টোগ্রাম আঁকতে চাই

2015/1/7  ===
2015/1/8  ===========
2015/1/9  ==========
2015/1/10 ====================================================================
2015/1/11 ===
2015/1/11 =
...

আপনি কি জানেন যে কোনও বাশ কমান্ড আছে যা আমাকে তা করতে দেয়?


1
বাশপ্লটলিব একটি দুর্দান্ত সমাধান
মাইকেল মায়ার

এটি স্বয়ংসম্পূর্ণ উত্তরের পরিবর্তে লিঙ্ক সরবরাহের অন্যতম ঝুঁকি। যদি মুছে ফেলা এসও উত্তরটি দরকারী হয় তবে দয়া করে এটি উত্তর হিসাবে এখানে পোস্ট করুন।
জেফ স্ক্যালার হলেন

উত্তর:


12

চেষ্টা করুন :

perl -lane 'print $F[0], "\t", "=" x ($F[1] / 5)' file

ব্যাখ্যা:

  • -a একটি স্পষ্ট split() মধ্যে @Fঅ্যারে, আমরা সঙ্গে মান পেতে$F[n]
  • x পার্লকে একটি অক্ষর এন টাইম প্রিন্ট করতে বলা হয়
  • ($F[1] / 5) : আমরা এখানে একটি সুন্দর মুদ্রণ আউটপুট জন্য নম্বর পেতে এবং এটি 5 দ্বারা বিভক্ত

1
perl -lane 'print $F[0], "\t", $F[1], "\t", "=" x ($F[1] / 3 + 1)'সত্যিই দুর্দান্ত
লাগছে

12

ইন perl:

perl -pe 's/ (\d+)$/"="x$1/e' file
  • eঅভিব্যক্তিটি মূল্যায়ন করার কারণ হয়, তাই আমি (সংখ্যার সাথে মিলে যাওয়া ) =এর মান ব্যবহার করে পুনরাবৃত্তি করি ।$1(\d+)
  • আপনি সংক্ষিপ্ত লাইন পেতে "="x($1\/3)পরিবর্তে "="x$1করতে পারেন। ( /যেহেতু আমরা একটি প্রতিস্থাপন কমান্ডের মাঝামাঝি আছি তখন পালানো যায়)

ইন bash( এই এসও উত্তর থেকে অনুপ্রাণিত ):

while read d n 
do 
    printf "%s\t%${n}s\n" "$d" = | tr ' ' '=' 
done < test.txt
  • printf$n ( %${n}s) এর প্রস্থ পেতে স্পেস ব্যবহার করে দ্বিতীয় স্ট্রিং প্যাড করে এবং আমি স্পেসগুলি এর সাথে প্রতিস্থাপন করি =
  • কলামগুলি একটি ট্যাব ( \t) ব্যবহার করে সীমাবদ্ধ করা হয় তবে আপনি এটিতে পাইপ দিয়ে সুন্দর করতে পারেন column -ts'\t'
  • আপনি সংক্ষিপ্ত লাইন পেতে $((n/3))পরিবর্তে ব্যবহার করতে পারেন ${n}

অন্য সংস্করণ:

unset IFS; printf "%s\t%*s\n" $(sed 's/$/ =/' test.txt) | tr ' ' =

আমি কেবল দেখতে পাচ্ছি যে আপনি sedযদি কিছুটা কমিয়ে দিতে চান তবে আপনাকে কোনও আউটপুট পাইপ করতে হবে , অন্যথায় এটি সবচেয়ে পরিষ্কার বিকল্প। যদি আপনার ইনপুট ফাইলের কোনও সম্ভাবনা থাকে তবে আপনার মধ্যে একটিতে [?*ডাব্লু / কমান্ডের নেতৃত্ব দেওয়া উচিত set -f;


2
ব্রাভোও শেল সলিউশন দেখানোর জন্য। আপনার পার্ল সমাধানটিও খুব পরিষ্কার।
ছানা

পছন্দ করুন সি প্রোগ্রামিংয়ে শিখেছি %*sএটি প্রথম- printfসম্পর্কিত সম্পর্কিত কৌশল হলেও আমি সর্বদা ভুলে যাই।
মুড়ু

printf(sed) | trসংস্করণ না এখানে যতটা আমি বলতে পারেন কাজ করে।
নাতিম

@ নাতিম এখানে কোথায় আছেন?
মুড়ু

যুক্তি দৈর্ঘ্যে @ মাইক্রোসভার সীমাবদ্ধতা সম্ভবত?
মুড়ু

6

সাথে সহজ awk

awk '{$2=sprintf("%-*s", $2, ""); gsub(" ", "=", $2); printf("%-10s%s\n", $1, $2)}' file

2015/1/7 ========
2015/1/8 =================================================
2015/1/9 ========================================
..
..

বা আমার প্রিয় প্রোগ্রামিং ভাষার সাথে

python3 -c 'import sys
for line in sys.stdin:
  data, width = line.split()
  print("{:<10}{:=<{width}}".format(data, "", width=width))' <file

3

কেমন:

#! /bin/bash
histo="======================================================================+"

read datewd value

while [ -n "$datewd" ] ; do
   # Use a default width of 70 for the histogram
   echo -n "$datewd      "
   echo ${histo:0:$value}

   read datewd value
done

যা উত্পাদন করে:

~/bash $./histogram.sh < histdata.txt
2015/1/7    ========
2015/1/8    =================================================
2015/1/9    ========================================
2015/1/10   ======================================================================+
2015/1/11   ===========
2015/1/12   ===
2015/1/13   =========
2015/1/14   ======================================================================+
2015/1/15   ==============================================================
2015/1/16   ==========
2015/1/17   ==============================
2015/1/18   ==============================
2015/1/19   =
2015/1/20   ===
2015/1/21   =======================
2015/1/22   ============
2015/1/24   ======
2015/1/25   ===
2015/1/27   ==
2015/1/28   ================
2015/1/29   =
2015/2/1    ============
2015/2/2    ==
2015/2/3    =
2015/2/4    ==========
2015/2/5    =============
2015/2/6    ==
2015/2/9    ==
2015/2/10   =========================
2015/2/11   =
2015/2/12   ======
2015/2/13   ============
2015/2/14   ==
2015/2/16   ========
2015/2/17   ========
2015/2/20   =
2015/2/23   =
2015/2/27   =
2015/3/2    ===
2015/3/3    ==
~/bash $

1

এটি একটি মজাদার traditionalতিহ্যগত কমান্ড লাইনের সমস্যা হিসাবে আমাকে আঘাত করেছে। এখানে আমার bashস্ক্রিপ্ট সমাধান:

awk '{if (count[$1]){count[$1] += $2} else {count[$1] = $2}} \
        END{for (year in count) {print year, count[year];}}' data |
sed -e 's/\// /g' | sort -k1,1n -k2,2n -k3,3n |
awk '{printf("%d/%d/%d\t", $1,$2,$3); for (i=0;i<$4;++i) {printf("=")}; printf("\n");}'

উপরের ছোট স্ক্রিপ্টটি ধরে নিয়েছে যে ডেটাটি একটি ফাইলের মধ্যে রয়েছে যার নাম "ডেটা" রয়েছে ative

আমি "এটিকে চালিয়ে দাও এবং সাজান" লাইনে খুব বেশি খুশি নই - আপনার মাস এবং মাসের দিনটি সর্বদা 2 ডিজিট থাকে তবে এটি অযথা হবে।

এছাড়াও, historicalতিহাসিক নোট হিসাবে, traditionalতিহ্যবাহী ইউনিক্সগুলি একটি কমান্ড লাইনের প্লটিং ইউটিলিটি নিয়ে আসত যা মোটামুটি কুৎসিত ASCII গ্রাফ এবং প্লট করতে পারে। নামটি মনে করতে পারছি না, তবে মনে হচ্ছে জিএনইউ প্লটুইটেলগুলি পুরানো traditional তিহ্যবাহী ইউটিলিটিটি প্রতিস্থাপন করে।


তা কি হওয়া উচিত নয় if ($1 in count) ...?
মুড়ু

1
@ মুরু - মনে হয় যেভাবেই কাজ করছে work যাইহোক, আমি "অন্য" ধারাটিতে টাইপোটি পেয়েছি। ধন্যবাদ।
ব্রুস এডিগার

1

এখানে দুর্দান্ত অনুশীলন। আমি "ডেটা" নামক একটি ফাইলে ডেটা ফেলে দিয়েছিলাম কারণ আমি খুব কল্পনাপ্রসূত।

ঠিক আছে, আপনি এটি বাশের জন্য চেয়েছিলেন ... এখানে এটি খাঁটি বাশে রয়েছে।

cat data | while read date i; do printf "%-10s " $date; for x in $(seq 1 $i); do echo -n "="; done; echo; done

awk একটি ভাল বিকল্প।

awk '{ s=" ";while ($2-->0) s=s"=";printf "%-10s %s\n",$1,s }' data

আপনি কি ফাইল ব্যবহারের পরিবর্তে উপস্থাপকের মাধ্যমে ডেটাটি পাইপ করতে পারেন?
নাতিম

হ্যাঁ, এটি কোনওভাবেই একই জিনিস। কেবল একটি "বিড়াল ডেটা |" যুক্ত করুন শুরুতে যেমন আমার কাছে ব্যাশ বিট, বা শেষে একটি "<ডেটা" ছিল। অথবা আপনি এমনকি কোনও ফাইল নির্দিষ্ট করে না দিয়ে কেবল মাত্র অর্ড অংশ রাখতে পারেন, ডেটাতে পেস্ট করুন এবং শেষে ctrl-D টিপুন। ফাইলটি নির্দিষ্ট করা কেবল সেই ফাইলটিকে স্টিডিন হিসাবে বিবেচনা করে এবং আমি অলস কারণ ডেটাফাইলে অনুলিপি এবং আটকানোতে চাইনি।
ফ্যালসনামস

1
আসলে, সহকর্মীর সাথে এটি সংযোগ করার সময় আমি কেবল প্রশ্নটি আবার পড়েছি ... আপনি বলেছিলেন যে আপনার কোনও ডেটা ফাইল নয় "আউটপুট" রয়েছে। সুতরাং যে রিপোর্টটি তৈরি করছে আপনি কেবল তা চালাতে পারেন, তারপরে এটি আঁকুন এবং আপনার কাজ শেষ। পাইপগুলি পরবর্তী কমান্ডের ইনপুট উত্স হিসাবে সর্বশেষ কমান্ডের কেবল প্রত্যক্ষ আউটপুট দেয়।
ফ্যালসনামস

0

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

while read value count; do
    printf '%s:\t%s\n' "${value}" "$(printf "%${count}s" | tr ' ' '=')"
done <path/to/my-output

একমাত্র জটিল অংশটি হচ্ছে বারটি নির্মাণ। আমি এখানে এই এসও উত্তরটি অর্পণ করেprintf এবং trপছন্দ করে

বোনাস হিসাবে, এটি পসিক্স-sh কমপ্লায়েন্ট।

তথ্যসূত্র:

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