ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
This will hopefully be fairly easy to answer as I know almost nothing about perl. I have a script that reads a file, manipulates it and sends it as an attached csv file in an e-mail. The part I need help with is as follows:
Code:
for $i(0..$#fields) {
$accounts .= "\"$fields[$i][0]\", \"$fields[$i][2]\", \"$fields[$i][1]\", \"$fields[$i][3]\"\n";
}
The attached file varies in length everyday depending on how large the original file is.
I need help with two things here.
1) Is it possible to put headers in the very first row of the csv file? So row one will always be the same and then row two and on will be the data.
2) Currently, the fields have quotation marks around them. How can I have the fields printed but remove the quotes? I thought I removed the quotes one time and none of the fields got printed after that.
You should use a CSV module, rather than reinventing the wheel. Text::CSV is one obvious choice.
You can easily print the headers as the first line. Simply save them as a scalar (say $headers), and then do this before you start to print the rest of the rows to the file.
Code:
print $out_fh "$headers\n";
That will print the $headers line to the filehandle $out_fh. You will need to have created and opened that filehandle first.
Can you show your data or how you're getting your data into the @fields array? It's hard to say much about the quotations problem without seeing the data itself.
You should use a CSV module, rather than reinventing the wheel. Text::CSV is one obvious choice.
You can easily print the headers as the first line. Simply save them as a scalar (say $headers), and then do this before you start to print the rest of the rows to the file.
Code:
print $out_fh "$headers\n";
That will print the $headers line to the filehandle $out_fh. You will need to have created and opened that filehandle first.
Can you show your data or how you're getting your data into the @fields array? It's hard to say much about the quotations problem without seeing the data itself.
Thanks Telemachos!
Here's the full code. It was written by someone else many years ago.
Code:
#!/usr/bin/perl
#
use MIME::Lite;
use Text::ParseWords;
my $MAX = 'user@domain.com';
my $MAILHOST = 'host.domain.com';
my $USERNAME = 'Mailman';
# Check the program's arguments
if(@ARGV != 1) {
print "Usage: GoogleFromNovell.pl <account file>\n";
exit;
}
# Read fields from ARGV[0] file
my(@fields, $line, $i);
open(FILE, $ARGV[0]);
$i = 0;
for $line(<FILE>) {
for ($line) {
s/^\s+//;
s/\s+$//;
}
@{$fields[$i]} = &parse_line(',', 0, $line);
$i++;
}
close(FILE);
# Make sure to send via smtp
MIME::Lite->send("smtp", "$MAILHOST");
# Email to mmcgrath
my $msg = MIME::Lite->new(
From =>"$USERNAME <$USERNAME\@host.domain.com>",
To =>"$MAX",
Subject =>"Google Mail User Accounts - " . localtime(),
Type =>"multipart/mixed"
);
# Message Body
$msg->attach(Type =>"TEXT",
Data =>"Google Mail User Accounts - " . localtime() . "\n"
);
# Actual account list (as an attachment)
my $accounts = "";
for $i(0..$#fields) {
$accounts .= "\"$fields[$i][0]\", \"$fields[$i][2]\", \"$fields[$i][1]\", \"$fields[$i][3]\"\n";
}
$msg->attach(Type =>"text/plain",
Filename =>"Google Mail User Accounts - " . localtime() . ".csv",
Disposition =>"attachment",
Data =>"$accounts"
);
# Send the message
$msg->send;
And here's what the data looks like from the file I'm getting.
The reason the orig programmer did that was in case of fields that have commas in them; defensive programming. It produces a nice consistent 'safe' csv file.
If you can guarantee(!) those fields will never have commas in them, then change that line to
The reason the orig programmer did that was in case of fields that have commas in them; defensive programming. It produces a nice consistent 'safe' csv file.
If you can guarantee(!) those fields will never have commas in them, then change that line to
I've made the changes and will check results tomorrow morning! I'll post back!
Thanks again!
Here's the code I used:
Code:
for $i(0..$#fields) {
$accounts .= "username,first name,last name,password\n;"
"$fields[$i][0],$fields[$i][2],$fields[$i][1],$fields[$i][3]\n";
}
All I got in my csv file was the first row of headers. After reviewing the code I noticed there was a semi-colon ending both lines. I've removed the one from the first line but will not see the results until Monday as the script doesn't run on Sunday. Does that sound like it would do the trick? As I do not know Perl, I'm only assuming that that is what caused my problem.
Or should I really consider using the print $out_fh "$headers\n"; as suggested above?
for $i(0..$#fields) {
$accounts .= "username,first name,last name,password\n;"
"$fields[$i][0],$fields[$i][2],$fields[$i][1],$fields[$i][3]\n";
}
Where did the "username,first name, last name, password\n" part come from? Based on your earlier code and what Chrism suggested, I would have thought you wanted this:
Code:
for $i(0..$#fields) {
$accounts .= "$fields[$i][0],$fields[$i][2],$fields[$i][1],$fields[$i][3]\n";
}
for $i(0..$#fields) {
$accounts .= "username,first name,last name,password\n;"
"$fields[$i][0],$fields[$i][2],$fields[$i][1],$fields[$i][3]\n";
}
Where did the "username,first name,last name,password\n" part come from? Based on your earlier code and what Chrism suggested, I would have thought you wanted this:
Code:
for $i(0..$#fields) {
$accounts .= "$fields[$i][0],$fields[$i][2],$fields[$i][1],$fields[$i][3]\n";
}
Edit: Now I see what happened. Your $accounts variable is what later fills the Data portion of your email. You put the headers into that and then assigned the actual rows & fields to nothing. Hence, they didn't get printed.
Try this maybe:
Code:
# Actual account list (as an attachment)
my $accounts = "username,first name,last name,password\n";
for $i(0..$#fields) {
$accounts .= "$fields[$i][0],$fields[$i][2],$fields[$i][1],$fields[$i][3]\n";
}
If I'm reading the script correctly, that should (1) set $accounts to the headers line and then (2) add the csv rows to $accounts inside the for loop.
Last edited by Telemachos; 10-17-2009 at 10:27 PM.
# Actual account list (as an attachment)
my $accounts = "username,first name,last name,password\n";
for $i(0..$#fields) {
$accounts .= "$fields[$i][0],$fields[$i][2],$fields[$i][1],$fields[$i][3]\n";
}
If I'm reading the script correctly, that should (1) set $accounts to the headers line and then (2) add the csv rows to $accounts inside the for loop.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.