একটি ফাইলের মধ্যে দীর্ঘতম রেখা কীভাবে প্রিন্ট করা যায়?


35

আমি কোনও ফাইলে দীর্ঘতম লাইন প্রিন্ট করার সহজ পদ্ধতির সন্ধান করছি। আমি কিছু গুগলিং করেছি এবং আশ্চর্যরূপে কোনও উত্তর খুঁজে পাওয়া যায়নি। আমি প্রায়শই একটি ফাইলে দীর্ঘতম লাইনের দৈর্ঘ্য মুদ্রণ করি তবে কীভাবে প্রকৃতপক্ষে দীর্ঘতম রেখাটি প্রিন্ট করা যায় তা আমি জানি না। যে কোনও ফাইলের মধ্যে দীর্ঘতম লাইন প্রিন্ট করার জন্য কোনও সমাধান দিতে পারে? আগাম ধন্যবাদ.


1
যখন একাধিক "দীর্ঘতম" লাইন থাকবে তখন কী হবে? যেহেতু আপনি একটি সর্বাধিক সর্বোচ্চ দৈর্ঘ্যের চেয়ে বেশি চান, আপনি কি লাইনগুলির দীর্ঘতম দৃষ্টান্তগুলি দেখতে চান?
পিটার.ও

উত্তর:


39
cat ./text | awk ' { if ( length > x ) { x = length; y = $0 } }END{ print y }'

ইউপিডি : মন্তব্যে সমস্ত পরামর্শ সংক্ষেপে

awk 'length > max_length { max_length = length; longest_line = $0 } END { print longest_line }' ./text 

3
এটি উভয় অন্য কমান্ড ( cat) কল করে এবং পাইপ ব্যবহার করা ব্যয়বহুল ক্রিয়াকলাপ, কেবল ফাইলটি পড়ার জন্য আরও বেশি কার্যকর এটি উল্লেখ করার দরকার নেই। যদি প্রায়শই এটি করা হয় তবে পারফরম্যান্সের প্রভাবগুলি অবশ্যই লক্ষণীয় এবং এরপরেও আপনি সম্পূর্ণ অপব্যবহার করছেন cat
ক্রিস ডাউন

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

4
@ কিথ থম্পসন: catএখানে অকেজো নয়। এটি কোনও কম্পিউটারের পক্ষে অকেজো হতে পারে তবে একটি মানব পাঠকের পক্ষে এটি মূল্য দিতে পারে। প্রথম বৈকল্পিক স্পষ্টভাবে ইনপুট দেখায়। প্রবাহটি আরও প্রাকৃতিক (বাম থেকে ডানে) is দ্বিতীয় ক্ষেত্রে আপনি জানবেন না যে আপনি উইন্ডোটি স্ক্রোল না করে ইনপুটটি কী।
jfs

1
@ জেএফএসবেস্টিয়ান এমনকি যদি আপনি এটি বামে চান তবে আপনার প্রয়োজন হবে না cat< file commandঠিক কাজ করে।
ক্রিস ডাউন

3
@ জেএফএসবেস্টিয়ান: কমান্ডের শুরুতে পুনর্নির্দেশটি লেখা যেতে পারে তা কিছুটা অস্পষ্ট; আমি চেষ্টা করেছি প্রতিটি শেলের < filename commandসমতুল্য filename < command। তবে একবার আপনি এটি সম্পর্কে অবগত হয়ে গেলে আপনি দীর্ঘ পাইপগুলি লেখার সময় এটির সুবিধা নিতে পারবেন যা স্পষ্টভাবে ডেটা প্রবাহের দিকনির্দেশ দেখায় (কোনও অতিরিক্ত আদেশ না দিয়ে):< input-file command1 | command2 | command3 > output-file
কিথ থম্পসন

6
cat filename | awk '{ print length }' | sort -n | tail -1

+1 এটির জন্য অনেক আকর্ষণীয় সমাধান ছিল তবে এটি ছিল সবচেয়ে সহজ। (বিড়ালটিকে ফাইলটি পড়ার দ্বারা বিড়াল ছাড়াই আরও সহজ হবে তবে কেন
বেঁধে

5
sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file

এটি প্রথমে কমান্ড প্রতিস্থাপনের মধ্যে ফাইলটি পড়ে এবং দীর্ঘতম লাইনের দৈর্ঘ্যকে আউটপুট করে (পূর্বে, expandট্যাবগুলিকে স্থানগুলিতে রূপান্তর করে, এর শব্দার্থকে কাটিয়ে উঠতে wc -L- লাইনের প্রতিটি ট্যাব 1 লাইন দৈর্ঘ্যের পরিবর্তে 8 যোগ করবে )। এই দৈর্ঘ্যটি তখন একটি sedঅভিব্যক্তিতে ব্যবহৃত হয় যার অর্থ "এই সংখ্যাটির দীর্ঘ অক্ষরের একটি রেখা সন্ধান করুন, এটি মুদ্রণ করুন, তারপরে প্রস্থান করুন"। সুতরাং এটি প্রকৃতপক্ষে সর্বোত্তম হতে পারে কারণ ফাইলের শীর্ষতম লম্বা লাইনটি নিকটে, হিহে (দুর্দান্ত এবং গঠনমূলক মন্তব্যের জন্য ধন্যবাদ ফিড)।

আরেকটি, আমি সেডের (বাশের মধ্যে) চেয়ে আগে ভেবেছিলাম:

#!/bin/bash
while read -r line; do
    (( ${#line} > max )) && max=${#line} && longest="$line"
done
echo "$longest"

2
এই পদ্ধতিটি খুব ব্যয়বহুল এবং ধীর।
ক্রিস ডাউন

2
@ ক্রিস ডাউন: ওহ হ্যাঁ এটি আছে। তবে প্রশ্নটি ছিল সবচেয়ে দক্ষ নয়, সবচেয়ে কড়া পদ্ধতি সম্পর্কে। ছোট থেকে মাঝারি ফাইল বা অ সমালোচনামূলক কাজের জন্য সূক্ষ্মভাবে WOrks।
এটা

3
সতর্কতা : -L, --max-line-lengthম্যান পৃষ্ঠা অনুসারে wc এর বিকল্পটি দীর্ঘতম রেখার দৈর্ঘ্য মুদ্রণ করে, তবে আপনি যদি গভীর খনন করেন (আপনি যখন ভুল / অপ্রত্যাশিত ফলাফল পেয়ে থাকেন) তবে আপনি দেখতে পাবেন যে এই বিকল্পটি প্রতিটি 1 ট্যাব চরের জন্য 8 দ্বারা দৈর্ঘ্য বৃদ্ধি করে find এই ইউনিক্স এবং লিনাক্স কিউ / এ\x09
পিটার.ও

গীত। আপনার উত্তরটি সমস্ত "সমানভাবে দীর্ঘতম" লাইনগুলি মুদ্রণ করবে, যা সম্ভবত একটি ভাল জিনিস ... ডাব্লুসিটি কে প্রতি ট্যাব প্রতি 1 টি চর গণনা করতে বাধ্য করে , এটি কাজ করে। sed -rn "/.{$(<file expand -t1 |wc -L)}/p" file
পিটার.ও

1
read lineআক্ষরিক গৃহস্থালির কাজ হিসাবে ব্যাকস্ল্যাশ-পলান অক্ষর, যেমন ব্যাখ্যা করবে \Aresloves করতে Aযা অবশ্যই কার্যকরভাবে একটি প্রকৃত চেয়ে খাটো বাইট-ব্যবহারের প্রতিবেদনগুলি, ... এটিকে রোধ করতে পলান ব্যাখ্যা, ব্যবহার: read -r line। । । । এছাড়াও, প্রথম "দীর্ঘতম লাইন" পরে p{p;q}sed -rn "/.{$(<file expand -t1 |wc -L)}/{p;q}" file
সেড

4

এখানে একটি পার্ল সমাধান:

perl -e 'while(<>){
           $l=length;  
           $l>$m && do {$c=$_; $m=$l}  
         } print $c' file.txt 

অথবা, আপনি যদি দীর্ঘতম সমস্ত লাইন মুদ্রণ করতে চান

perl -e 'while(<>){
           $l=length;
           push @{$k{$l}},$_;
           $m=$l if $l>$m;
         } print @{$k{$m}}' file.txt 

যেহেতু আমার কাছে এর চেয়ে ভাল আর কিছুই ছিল না, তাই আমি 625 এম পাঠ্য ফাইলটিতে কিছু বেঞ্চমার্ক চালিয়েছি। আশ্চর্যজনকভাবে, আমার পার্ল সমাধানটি অন্যদের তুলনায় ধারাবাহিকভাবে দ্রুত ছিল। মঞ্জুর, স্বীকৃত সঙ্গে পার্থক্যawk সমাধানের ক্ষুদ্র, তবে এটি রয়েছে। স্পষ্টতই, একাধিক লাইন মুদ্রণকারী সমাধানগুলি ধীর হয় তাই আমি প্রকার অনুসারে বাছাই করেছি, সবচেয়ে দ্রুততম।

দীর্ঘতম লাইনগুলির মধ্যে একটিতে মুদ্রণ করুন:

$ time perl -e 'while(<>){
           $l=length;  
           $l>$m && do {$c=$_; $m=$l}  
         } print $c' file.txt 
real    0m3.837s
user    0m3.724s
sys     0m0.096s



$ time awk 'length > max_length { max_length = length; longest_line = $0 }
 END { print longest_line }' file.txt
real    0m5.835s
user    0m5.604s
sys     0m0.204s



$ time sed -rn "/.{$(<file.txt expand -t1 |wc -L)}/{p;q}" file.txt 
real    2m37.348s
user    2m39.990s
sys     0m1.868s

সমস্ত দীর্ঘতম লাইন মুদ্রণ করুন:

$ time perl -e 'while(<>){
           $l=length;
           push @{$k{$l}},$_;
           $m=$l if $l>$m;
         } print @{$k{$m}}' file.txt 
real    0m9.263s
user    0m8.417s
sys     0m0.760s


$ time awk 'length >x { delete y; x=length }
     length==x { y[NR]=$0 } END{ for (z in y) print y[z] }' file.txt
real    0m10.220s
user    0m9.925s
sys     0m0.252s


## This is Chris Down's bash solution
$ time ./a.sh < file.txt 
Max line length: 254
Lines matched with that length: 2
real    8m36.975s
user    8m17.495s
sys     0m17.153s

3

প্রথম দীর্ঘতম লাইনটি গ্রেপ করুন

grep -Em1 "^.{$(wc -L <file.txt)}\$" file.txt 

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

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

কমান্ডটির দুটি অংশ রয়েছে, একটি grep- এবং একটি wcআহবান:

## grep "^.{$( wc -L F )}$" F

wcএকটি প্রক্রিয়া সম্প্রসারণ ব্যবহার করা হয় $( ... ), তাই এটি সামনে চালানো হয় grep। এটি দীর্ঘতম লাইনের দৈর্ঘ্য গণনা করে। শেল এক্সপেনশন সিনট্যাক্সটি একটি বিভ্রান্তিকর উপায়ে নিয়মিত এক্সপ্রেশন প্যাটার্ন সিনট্যাক্সের সাথে মিশ্রিত হয়, তাই আমি প্রক্রিয়া সম্প্রসারণকে পচন করব:

## wc -L F
42
## grep "^.{42}$" F

এখানে, প্রক্রিয়া সম্প্রসারণটি যে মানটি ফিরে আসবে তার সাথে প্রতিস্থাপন করা হয়েছিল, grepব্যবহৃত কমান্ডলাইন তৈরি করে । আমরা এখন নিয়মিত প্রকাশটি আরও সহজেই পড়তে পারি: এটি শুরু ( ^) থেকে শেষ পর্যন্ত ঠিক মেলে ($ লাইনের ) । তাদের মধ্যে প্রকাশটি নিউলাইন ছাড়া অন্য কোনও চরিত্রের সাথে মিলিত হয়, যা 42 বার পুনরাবৃত্তি হয়। একত্রিত, এটি হ'ল লাইন যা হুবহু 42 টি অক্ষর নিয়ে গঠিত।


এখন, রিয়েল শেল কমান্ডগুলিতে ফিরে আসুন: grepঅপশন -E( --extended-regexp) {}পঠনযোগ্যতার জন্য এড়ানোর অনুমতি দেয় । বিকল্প -m 1( --max-count=1) প্রথম লাইন সন্ধানের পরে এটি বন্ধ করে দেয়। <মধ্যে wcকমান্ড প্রতিরোধ তার stdin ফাইল লিখছেন, wcদৈর্ঘ্য সঙ্গে একসঙ্গে ফাইলের নাম মুদ্রণ থেকে।

কোন দীর্ঘতম রেখা?

ফাইল নামটি দু'বার সংঘটিত হওয়ার সাথে উদাহরণগুলি আরও পঠনযোগ্য করার জন্য, আমি fফাইলনামের জন্য একটি ভেরিয়েবল ব্যবহার করব ; $fউদাহরণের প্রতিটি ফাইলের নাম দ্বারা প্রতিস্থাপিত হতে পারে।

f="file.txt"

প্রথম দীর্ঘতম রেখাটি দেখান - প্রথম লাইনটি দীর্ঘতম রেখার মতো দীর্ঘ:

grep -E -m1 "^.{$(wc -L <"$f")}\$" "$f"

সমস্ত দীর্ঘতম রেখা দেখান - সমস্ত লাইন দীর্ঘতম রেখার মতো দীর্ঘ:

grep -E "^.{$(wc -L <"$f")}\$" "$f" 

সর্বশেষতম লাইনটি দেখান - সর্বশেষ লাইনটি দীর্ঘতম রেখার মতো দীর্ঘ:

tac "$f" | grep -E -m1 "^.{$(wc -L <"$f")}\$"

একক দীর্ঘতম লাইনটি দেখান - অন্যান্য সমস্ত লাইনের চেয়ে দীর্ঘতম লাইন বা ব্যর্থ:

[ $(grep -E "^.{$(wc -L <"$f")}\$" "$f" | wc -l) = 1 ] && grep -E "^.{$(wc -L <"$f")}\$" "$f" 

(শেষ কমান্ড যেমন সম্পূর্ণ grep কমান্ড প্রয়োগ পুনরাবৃত্তি অন্যদের তুলনায় আরও বেশি অদক্ষ হয়। এটা সম্ভবত পচে করা উচিত যাতে আউটপুট wcএবং দ্বারা লিখিত লাইন grepভেরিয়েবল সংরক্ষিত আছে।
নোট করুন যে সমস্ত দীর্ঘতম লাইন আসলে সব লাইন হতে পারে ভেরিয়েবলে সঞ্চয় করার জন্য কেবল প্রথম দুটি লাইনই রাখা দরকার))


বাহ দুর্দান্ত উত্তর, এর থেকে অনেক কিছু শিখলাম। ধন্যবাদ
কিছু কিছু 18

2

নিম্নলিখিত উদাহরণটি দিমিত্রি.মালিকভের উত্তরের মন্তব্য, এবং হওয়া উচিত ছিল , তবে দৃশ্যমান মন্তব্য স্পেসের অকেজো ব্যবহারের কারণে সেখানে , আমি এটি এখানে উপস্থাপন করতে বেছে নিয়েছি, যেখানে এটি কমপক্ষে দেখা যাবে। ..

এটি দিমিত্রি এর একক-পাস অজক পদ্ধতিটির একটি সহজ প্রকরণ ।
এটি সমস্ত "সমান দীর্ঘতম" লাইনগুলি মুদ্রণ করে। (দ্রষ্টব্য। delete arrayএকটি ছদ্মবেশী এক্সটেনশন)।

awk 'length >x { delete y; x=length }
     length==x { y[NR]=$0 } END{ for (z in y) print y[z] }' file

1

খাঁটি বাশে:

#!/bin/bash

_max_length=0
while IFS= read -r _line; do
    _length="${#_line}"
    if (( _length > _max_length )); then
        _max_length=${_length}
        _max_line=( "${_line}" )
    elif (( _length == _max_length )); then
        _max_line+=( "${_line}" )
    fi
done

printf 'Max line length: %d\n' "${_max_length}"
printf 'Lines matched with that length: %d\n' "${#_max_line[@]}"
(( ${#_max_line[@]} )) && printf '%s\n' '----------------' "${_max_line[@]}"

যেমনটি রয়েছে, কোডটি অবৈধ ফলাফল দিতে পারে। সেটিং _max_line[0]=${_line}এর আগে আর জমা হওয়া সংক্ষিপ্ত "দীর্ঘতম লাইন" unset _max_line
বাকীটি সরায় না

@ ফেড এর জন্য ধন্যবাদ, খুব দ্রুত লেখা হয়েছিল। সংশোধন করা হয়েছে।
ক্রিস ডাউন

0

আমি এটির জন্য একটি ছোট শেল স্ক্রিপ্ট তৈরি করেছি। এটি দৈর্ঘ্য, লাইন # এবং লাইনটি নিজেই দৈর্ঘ্যের সাথে দেখায় যা নির্দিষ্ট আকারের চেয়ে 80 টি অক্ষরের বেশি:

#!/bin/sh

# Author: Surinder

if test $# -lt 2
then
   echo "usage: $0 length file1 file2 ..."
   echo "usage: $0 80 hello.c"
   exit 1
fi

length=$1

shift

LONGLINE=/tmp/longest-line-$$.awk

cat << EOF > $LONGLINE
  BEGIN {
  }

  /.*/ {
    current_length=length(\$0);
    if (current_length >= expected_length) {
       printf("%d at line # %d %s\n", current_length, NR, \$0);
    }
  }

  END {
  }
EOF

for file in $*
do
  echo "$file"
  cat $file | awk -v expected_length=$length -f $LONGLINE |sort -nr
done

rm $LONGLINE

https://github.com/lordofrain/tools/blob/master/longest-line/longest-line.sh


1
আপনি কিছু উন্নতি করতে পারেন। আপনার পরিবর্তনশীল উদ্ধৃতি । এটি হোয়াইটস্পেস বা অন্যান্য অদ্ভুত অক্ষর ধারণ করে এমন কোনও ফাইলের নাম ভাঙবে। ব্যবহার $*করা খুব কমই একটি ভাল ধারণা, আপনি চান"$@"/.*/আপনার awkযেহেতু যে পাশাপাশি খালি লাইন মিলে যায় কিছু না। আপনি \$0একক উদ্ধৃতি দিলে আপনি পালাতে এড়াতে পারেন 'EOF'। খালি BEGIN{}ব্লক কেন ব্যবহার করবেন ? অবশেষে, আপনার দরকার নেই cat, কেবলawk . . . "$file" | . . .
টেরডন

1
আপনি পুরোপুরি প্রত্যক্ষভাবে সরাসরি awk -vmax=15 '{len=length($0); if(len>=max){printf("%s, %d at line # %d %s\n", FILENAME, len, NR, $0);}}' file*
কাজটিও করেছিলেন

-3

আপনি ব্যবহার করতে পারেন wc:

wc -L fileName

3
প্রশ্নটি আবার পড়ুন। প্রয়োজনীয় আউটপুটটি দীর্ঘতম লাইন নিজেই, দীর্ঘতম লাইনের দৈর্ঘ্য নয়। এর অপূর্ণতা সম্পর্কে পিটার.ও'র মন্তব্য দেখুন wc -L
manatwork
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.