LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 07-16-2010, 07:46 AM   #16
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713

Code:
#!/usr/bin/env perl

open my $file, $ARGV[1] or die "Could not open file";
while (<$file>) # iterate over the lines
{
    s/D/e/g;
    for (split) # iterate over the columns in the current line
    {
        $_ *= 219474.6306726;
        print "$_\n";
    }
}
close $file;
I have no idea if this will work, I'm still a bit new to Perl, but I couldn't resist .

Last edited by MTK358; 07-16-2010 at 09:16 AM.
 
Old 07-16-2010, 07:59 AM   #17
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Quote:
Originally Posted by MTK358 View Post
I have no idea if this will work, I'm still a bit new to Perl, but I couldn't resist .
Nice attempt! I'm not a perl expert, too... but I'm afraid it parses the file row by row, whereas we need a trick to parse by columns.
 
Old 07-16-2010, 08:00 AM   #18
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,541

Rep: Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919
Well I was hoping you would work the line number issue out, but it you were on the right track as to use NR:
Code:
awk '{for(i=1;i<=NF;i++)if(arr[i] ~ /./)arr[i]=arr[i]"\n"NR" "$i;else arr[i]=NR" "$i}END{for(x=1;x<=length(arr);x++)printf("%s\n",arr[x])}' in_file
I am not sure how this affect your double precision.

btw. I realise you were giving us a dumbed down example, but as you can see for future questions, dealing with floating point precision can make a large impact
if not known about earlier

Edit: Also, maybe you could show us some actual input? (changed to protect the data of course if necessary)

Last edited by grail; 07-16-2010 at 08:21 AM.
 
Old 07-16-2010, 08:27 AM   #19
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Hi grail! Your code is neat as always, but why not using just a counter to print the line number? Just another suggestion (a lot of work for the original poster ) but I would end-up with something like this:
Code:
BEGIN { factor = 219474.6306726 }

{
  gsub(/D/,"E")
  
  for ( i=1; i<=NF; i++ )
     array[++count] = $i
}

END {
  for ( i=1; i<=count/NR; i++ ) {
    for ( j=0; j<NR; j++ ) {
      print ++c, array[i+j*NF] * factor
    }
  }
}
 
Old 07-16-2010, 09:12 AM   #20
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
Quote:
Originally Posted by colucix View Post
Nice attempt! I'm not a perl expert, too... but I'm afraid it parses the file row by row, whereas we need a trick to parse by columns.
No, the while loop goes through the file line by line, all instances of 'D' are replaced with 'e', and the for loop goes through the current line column by column.

It makes heavy use of the implicit $_ variable.

Last edited by MTK358; 07-16-2010 at 09:15 AM.
 
Old 07-16-2010, 09:18 AM   #21
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,541

Rep: Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919
Quote:
Originally Posted by colucix
but why not using just a counter to print the line number?
Hey Colucix

Based on the OPs original request they wanted the line numbers to equal the line the column came from as opposed to where your code has an ever increasing
count, ie if there are 3 rows and 3 columns it would be

1 a1
2 a2
3 a3
1 b1
2 b2
...
 
Old 07-16-2010, 09:40 AM   #22
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,541

Rep: Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919
So after a little plagiarism from colucix (hope you don't mind ):
Code:
BEGIN { factor = 219474.6306726 }

{
    gsub(/D/,"E")

    for(i=1;i<=NF;i++)
    {
        if(arr[i])
            arr[i]=arr[i]"\n"

        arr[i]=arr[i]NR" " $i * factor
    }
}

END{
    for(x=1;x<=NF;x++)
        print arr[x]
}
 
Old 07-16-2010, 10:08 AM   #23
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Quote:
Originally Posted by grail View Post
Based on the OPs original request they wanted the line numbers to equal the line the column came from as opposed to where your code has an ever increasing count
Uh, sorry... I missed that part. A little modification to my previous code:
Code:
BEGIN { factor = 219474.6306726 }

{
  gsub(/D/,"E")
  
  for ( i=1; i<=NF; i++ )
     array[++count] = $i
}

END {
  for ( i=1; i<=count/NR; i++ ) {
    for ( j=0; j<NR; j++ ) {
      print j+1, array[i+j*NF] * factor
    }
  }
}
Quote:
Originally Posted by grail View Post
So after a little plagiarism from colucix (hope you don't mind ):
That's about it!
 
Old 07-16-2010, 10:29 AM   #24
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,541

Rep: Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919
@colucix - I still like the simplicity of your sequence, but I forgot to ask ... what does the pipe into 'n1' do?

Edit: Ignore last part ... I am an idiot .. it is the letter 'l' ...

Last edited by grail; 07-16-2010 at 10:34 AM.
 
Old 07-16-2010, 10:38 AM   #25
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Quote:
Originally Posted by MTK358 View Post
No, the while loop goes through the file line by line, all instances of 'D' are replaced with 'e', and the for loop goes through the current line column by column.

It makes heavy use of the implicit $_ variable.
Yup. But it should not print the splitted fields immediately, otherwise you get alternate output as you read it from left to right, e.g.
Code:
$ cat test.pl
#!/usr/bin/env perl
open $file, $ARGV[0] or die "Could not open file: $!";
while (<$file>) {
    s/D/e/g;
    for (split)
    {
        $_ *= 219474.6306726;
        print "$_\n";
    }
}
close $file or die "$file: $!";
$ cat file
1.0000D-05  2.0000D-05  3.0000D-05
1.0000D-05  2.0000D-05  3.0000D-05
1.0000D-05  2.0000D-05  3.0000D-05
$ ./test.pl file
2.194746306726
4.389492613452
6.584238920178
2.194746306726
4.389492613452
6.584238920178
2.194746306726
4.389492613452
6.584238920178
$
whereas it should be
Code:
2.194746306726
2.194746306726
2.194746306726
4.389492613452
4.389492613452
4.389492613452
6.584238920178
6.584238920178
6.584238920178
 
Old 07-16-2010, 10:40 AM   #26
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Quote:
Originally Posted by grail View Post
Edit: Ignore last part ... I am an idiot .. it is the letter 'l' ...
He he! Anyway, as you pointed out, it was wrong in this context.
 
Old 07-16-2010, 10:47 AM   #27
grail
Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 7,541

Rep: Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919Reputation: 1919
Quote:
Originally Posted by colucix
it was wrong in this context
Yeah but a little ++counter fixed that (mainly cause I couldn't workout how to use the sequence numbers again as the counter )
Code:
eval cat $(seq -f "<(awk '{sub(/D/,\"E\"); print ++n\" \"$%.0f''*''219474.6306726}' file)" 1 6)
 
Old 07-16-2010, 11:05 AM   #28
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Great!

Just a little note (then I will stop... promised ): why do you use a quoted space in the print statement? Comma separated arguments will be printed out as OFS separated strings. I find the comma more elegant and quick to type.
 
Old 07-16-2010, 11:36 AM   #29
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713Reputation: 713
Quote:
Originally Posted by colucix View Post
Yup. But it should not print the splitted fields immediately, otherwise you get alternate output as you read it from left to right, e.g.
Code:
$ cat test.pl
#!/usr/bin/env perl
open $file, $ARGV[0] or die "Could not open file: $!";
while (<$file>) {
    s/D/e/g;
    for (split)
    {
        $_ *= 219474.6306726;
        print "$_\n";
    }
}
close $file or die "$file: $!";
$ cat file
1.0000D-05  2.0000D-05  3.0000D-05
1.0000D-05  2.0000D-05  3.0000D-05
1.0000D-05  2.0000D-05  3.0000D-05
$ ./test.pl file
2.194746306726
4.389492613452
6.584238920178
2.194746306726
4.389492613452
6.584238920178
2.194746306726
4.389492613452
6.584238920178
$
whereas it should be
Code:
2.194746306726
2.194746306726
2.194746306726
4.389492613452
4.389492613452
4.389492613452
6.584238920178
6.584238920178
6.584238920178
I didn't realize that.

Code:
#!/usr/bin/env perl

open my $file, $ARGV[1] or die "Could not open file";
for my $col (0 .. 2)
{
    seek $file, 0, SEEK_SET;
    
    while (<$file>)
    {
        my @cols = split;
        $_ = $cols[$col];
        s/D/e/g;
        $_ *= 219474.6306726;
        print "$_\n";
    }
}
close $file;
 
Old 07-16-2010, 12:58 PM   #30
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,506

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Nice! It works for me. It misses only the line numbers part.

Edit: just notice that the first argument in perl is $ARGV[0].

Last edited by colucix; 07-16-2010 at 01:00 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Column statistic by awk ? cs24 Programming 7 01-15-2010 05:41 AM
Read text file column by column RVF16 Programming 11 05-31-2009 07:16 AM
Change column value with AWK RyudoBlaze Programming 2 04-25-2009 03:05 AM
Concatenate column 1 and column 2 of related lines cgcamal Programming 4 11-20-2008 10:43 AM
awk column printing schneidz Programming 7 09-29-2005 06:14 AM


All times are GMT -5. The time now is 04:03 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration