Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Read text file and output in different format

Status
Not open for further replies.

jess916

Programmer
Aug 26, 2008
11
0
0
US
I am new to Perl so this may be a rather simple task, but I have tab delimited text file that I need to parse through(except the comments that have quotations). For example if I have the following data in a text file what would be the best way to write a script that would output the data in a different format shown below?

Input(txt file):
Bob night "schedule is flexible"
Jerry night
Larry day "fixed schedule"
Mary mid

Desired Output:

day Larry
mid Mary
night Bob //Comments if any
night Jerry //Comments if any
 
School work from students is not allowed to be posted here. Not sure if that is school work but it looks like it could be.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
I have outlined the steps I want to take to get the code but since i just started learning the language last week, it has been a challange. Here is what I have so far.

#!/usr/bin/perl
open ( MYFILE, '<in.txt' );
open ( OUTFILE, '>out.txt' );
$name = <STDIN>;
chomp($name);
print OUTFILE "$name( \n";
while ($data = <MYFILE>) {
chomp($data);
if (/\t*mid/) {
print OUTFILE "mid $data\n"; #this doesn't work yet b/c I #need it to only print the name
}
}
print OUTFILE "\nEnd\n";
close (MYFILE);
close (OUTFILE);
 
Hi KevinADC,

I assure you this is not schoolwork. The data is made up I acutally need this to expedite the process of writing Verilog code which contains signals, direction, and comments. I am taking the netlist, sorting by direction and would like to use Perl to output the verilog format. Due to the confidentiality of my employer I didn't want to reveal any sensitive information such as the actual data in the text files. Any help would be appreciated.

Regards,
Jessica
 
You can replace the while (<DATA>) bit with your file handle (in the code you posted above, it would be while (<MYFILE>).) And everything from __DATA__ on is being used as a file handle (instead of your text file) so that can be removed when you substitute your file.

Also, this will print the results in the same order they appear in the input text file. In your example it appears the "output" is sorted based on the shift - is this a requirement? If you need the output sorted, the code will need to be modified.

Code:
use warnings;
use strict;

while (<DATA>) {
	chomp;
	my ($name, $shift, $comments) = split /\t+/, $_, 3;
	if (defined $comments) {
		$comments =~ s/"//g;	# Remove " characters
		print join("\t", $shift, $name, "//" . $comments), "\n";
	} else {
		print join("\t", $shift, $name), "\n";
	}
}

__DATA__
Bob		night	"schedule is flexible"
Jerry	night
Larry	day		"fixed schedule" 
Mary	mid
 
Post some real data but with sensitive stuff altered. Right now it looks like you want "day" first, then "mid", then "night" and the names in alpha order respective to the day/mid/night key. In order to do that you will need to read the entire file, then sort, or ouput three seperate files, a day, a mid, a night, sort each file then combine them back into one file. But you can not sort them on-the-fly.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
When I tried your code rharsh, it outputs:

Code:
	Bob        night    "schedule is flexible"
	Jerry    night
	Larry    day        "fixed schedule"
	Mary    mid

which looks suspiciously like the original data ;)

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
after changing the split argument to /\s+/ it outputs:

Code:
night	Bob	//schedule is flexible
night	Jerry
day	Larry	//fixed schedule
mid	Mary

which is not sorted but does put the // before the comments


------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
LOL! It does, that's not good.

When I run it I get:
Code:
night   Bob     //schedule is flexible
night   Jerry
day     Larry   //fixed schedule
mid     Mary
It must be that the tabs are getting converted to spaces on here.

Just in case, how about:
Code:
my ($name, $shift, $comments) = split /[red][b]\s[/b][/red]+/, $_, 3;
 
You're right Kevin, thanks!

Oh, and the sorting bit:
rharsh said:
In your example it appears the "output" is sorted based on the shift - is this a requirement? If you need the output sorted, the code will need to be modified.
I thought I'd see if it was a requirement before I worried about it. [thumbsup2]
 
Thanks guys! I was actually able to figure something out. The code posted below seemed to work (minus the comments). Also rharsh I doesn't need to be sorted. Thank you again!!

Code:
#!/usr/bin/perl

open ( MYFILE, '<Netlist.txt' );
open ( OUTFILE, '>Verilog.txt' );
$name = <STDIN>;
chomp($name);
print OUTFILE "Module $name( \n";
while ($data = <MYFILE>) {
chomp;
print OUTFILE "$1\n" if $data =~ /^\s*(\S+)\s+(input|output)/
}
print OUTFILE ");\n";
close (MYFILE);
open ( MYFILE, '<test2.txt' );
while ($data = <MYFILE>) {
chomp($data);
if ($data =~ /^\s*(\S+)\s+(input)/) { 
print OUTFILE "Input $1\n"; 
}
elsif ($data =~ /^\s*(\S+)\s+(output)/) {
print OUTFILE "Output $1\n";
}
else {
print "\n";
}
}
print OUTFILE "\nEndmodule\n";
close (MYFILE);
close (OUTFILE);
 
Sorry forgot the sample data...
Input:

signal1 Input "comments"
signalA Input
signal2 Output "comments"
signalB Output

This is the format I get from my code:

Module name(
signal1
signalA
signal2
signalB
);
input signal 1
input signal A
output signal 2
output signal B

Endmodule
 
untested code to add the //comments to the output:

Code:
#!/usr/bin/perl

open ( MYFILE, '<Netlist.txt' );
open ( OUTFILE, '>Verilog.txt' );
$name = <STDIN>;
chomp($name);
print OUTFILE "Module $name( \n";
while ($data = <MYFILE>) {
   chomp;
   print OUTFILE "$1\n" if $data =~ /^\s*(\S+)\s+(input|output)/
}
print OUTFILE ");\n";
close (MYFILE);

open ( MYFILE, '<test2.txt' );
while ($data = <MYFILE>) {
   chomp($data);
   my $coms = '';
   if ($data =~ /^\s*(\S+)\s+(Input|Output)\s*(.*)/) {
      if ($3) {
         $coms = $3;
         $coms =~ tr/"//d;
         $coms = " //$coms";
      }
      print OUTFILE "$2 $1$coms\n";
   }
   else {#<--- might not be necessary
      print "\n";
   }
}
print OUTFILE "\nEndmodule\n";
close (MYFILE);
close (OUTFILE);

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Thanks this worked great. I just had to had one more else statement for the names without comments.
Code:
else {
         print OUTFILE "$3 $2\t$1;\n";
}

 
hmmm.... It looks like my code would handle with or without comments, but since I did not test it too much maybe not.

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top