Please help me!I want the code for doing following task in perl. Task is that "Read the paragraph from a file and print it in another file in ascending(total number of words in a sentence) order." My sample task:
If the input "Hi! my name is Sarma. Can you help?"
Output should be "Hi! Can you hepl? my name is Sarma."                  
I could try this. It prints the number of words in a each sentence. My code is:


#!/usr/local/bin/perl


use strict;
use warnings;

my ($line,$inFile,$outFile,$para, $text, @sentences, @words, @length, $count, $i, $order);  #defined variables
$inFile = "name.txt";
$outFile = "out.txt";

open (SOURCE, $inFile) || die "cannot open \"$inFile\": $!";
open (RESULT, ">$outFile") || die "cannot open \"$outFile\": $!";


while ($line = <SOURCE>) {

chomp($line);
$text = $text.$line;

}
close (SOURCE);

@sentences = split(/[!,?,.]/, $text);   #split text into sentences
for ($i=0;$i<scalar(@sentences);$i++)
{
@words=split(/\s+/, @sentences[$i]);    #split each sentence into words
@length = scalar(@words);   #count words of the sentence
my @array = sort @length;
print RESULT "@array\n";

}

close (RESULT);

Dani AI

Generated

Short, practical addendum.

The core mistakes in the original post are easy to fix: splitting on a character class like /[!,?,.]/ throws away the sentence-ending punctuation and produces empty fragments; updating a single @length or using the sentence text as a hash key destroys duplicate sentences and original ordering. As pointed out, collect all sentences and their counts first, then sort; and as showed, counting by value works — but a hash will deduplicate identical sentences, which is usually not desired.

A safe pattern is: slurp the file, extract sentences while keeping their trailing punctuation, count word tokens with a regex that treats contractions and hyphenated forms as single words, collect records that include the original index (so ties are stable), sort ascending by count, then write the sentences back joined with single spaces. The code below is a concise example that follows that pattern.

#!/usr/bin/perl
use strict;
use warnings;

my ($infile, $outfile) = ('name.txt', 'out.txt');
local $/;
open my $in,  '<', $infile  or die "open $infile: $!";
my $text = <$in>;
close $in;

my @sent;
while ($text =~ /(\s*.*?[.!?]+)(?=\s|$)/gs) {
    my $s = $1;
    $s =~ s/^\s+|\s+$//g;
    my $count = () = $s =~ /[A-Za-z0-9]+(?:['-][A-Za-z0-9]+)*/g;
    push @sent, { text => $s, count => $count, idx => scalar @sent };
}
# optional: capture trailing fragment without terminal punctuation
if ($text =~ /(\S.*\S)\s*$/ and $1 !~ /[.!?]$/) {
    my $s = $1;
    my $count = () = $s =~ /[A-Za-z0-9]+(?:['-][A-Za-z0-9]+)*/g;
    push @sent, { text => $s, count => $count, idx => scalar @sent };
}

my @sorted = sort { $a->{count} <=> $b->{count} || $a->{idx} <=> $b->{idx} } @sent;
open my $out, '>', $outfile or die "open $outfile: $!";
print $out join(' ', map { $_->{text} } @sorted), "\n";
close $out;

Notes: this approach preserves punctuation and duplicates, and uses a stable tie-breaker (original position). For production text with abbreviations, ellipses, quoted dialogue or Unicode, consider a CPAN sentence tokenizer (e.g., Lingua::EN::Sentence) and enable UTF-8 handling.

Recommended Answers

All 2 Replies

Looks like your logic has a few problems.
1. You are iterating through the sentences but you are storing the words and lengths in arrays that will only contain a single element. (That is, you are overwriting the values in @words and @length on each pass because you aren't either indexing the array when you store them or adding them to the end of the existing arrays.)
2. Plus, you are sorting and printing this single item array each time you process a sentence when it seems you'd want to sort and print the results after processing all sentences.
3. It also seems that since you're only sorting and printing the length, you won't get the actual text printed.

Consider using a multi-dimensional array so you can easily associate the counts with the text.

Try this.
Using a hash and sorting by value

#!/opt/local/bin/perl5
my $in="in";
my $out="out";
my $line;
my $text;
my @sentences;
my %seen;
open(SOURCE,"<in") or die $!."\n";
while ($line = <SOURCE>) {
chomp($line);
$text = $text.$line;
}
close(SOURCE);
@sentences = split(/[!,?,.]/, $text);

foreach(@sentences){
        my $dummy=$_;
        $dummy=~s/^\s//g;##removing any beginning space
        $seen{$dummy}=scalar(split(/\s+/,$dummy));
}
#print hash as key value pair
#while(($key,$value)=each(%seen)){
#        print "$key => $value\n";
#}
#sort hash by value

open(FOUT,">out");
foreach $value (sort {$seen{$a} <=> $seen{$b} }
           keys %seen)
{
     print FOUT "$value\n";
}
close(FOUT);

cat out
Hi
Can you help
my name is Sarma

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.