3

PerlとDBIモジュールを使用してSQLServerデータベースからデータを読み取ろうとしています。私の意図は、データを読み取り、テキストファイル(カンマ区切り)に印刷することです。これを行うと、次のような結果が得られます。

var1,var2,var3
40406,20 ,783
50230,78 ,680
50230,78 ,680
50230,78 ,680
50230,78 ,680

したがって、2番目の変数データとコンマの間には空白があります。以下のコードを使用してこれをトリミングしようとしましたが、機能しませんでした。これらの空白を取り除くためにコードをどのように変更する必要がありますか?

私のコードはここにあります:

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

sub trim;

my $dbs = "dbi:ODBC:DRIVER={SQL Server};SERVER={xxxx}";
my ($username, $password) = ('un', 'pwd');

my $dbh = DBI->connect($dbs, $username, $password)
               or die "Can't connect to $dbs: $DBI::errstr";

my $sth = $dbh->prepare("select var1, var2, var3 from db.dbo.table")
                or die "Can't prepare statement: $DBI::errstr";

$sth->execute();

my $outfile = 'temp.txt';
open OUTFILE, '>', $outfile or die "Unable to open $outfile: $!";

print OUTFILE join(",", @{$sth->{NAME}}), "\n";

while (my @re = $sth->fetchrow_array) {
   print OUTFILE join(",", trim(@re)), "\n";
}

close OUTFILE;

$sth->finish();
$dbh->disconnect();

############## subroutines ##################
sub trim($) {
    my $string = shift;
    $string =~ s/^\s+//;
    $string =~ s/\s+$//;
    return $string;
}
4

3 に答える 3

5

trim() 関数は、その場でリストを変更しません (また、リストを処理しません)。

したがって、実際の TIMTOWTDI のやり方では、新しい配列を返すように関数を変更する必要があります。

sub trimArray {
    my @arr = @_;
    my @rv;
    for my $val (@arr) {
        $val =~ s/^\s+//;
        $val =~ s/\s+$//;
        push @rv, $val;
    }
    return @rv;
}

#and then

print OUTFILE join(",", trimArray(@re)), "\n";

または、関数への参照を渡し、その場で配列を変更します

sub trimInPlace {
    my $arrRef = shift;
    for my $val (@$arrRef) {
        $val =~ s/^\s+//;
        $val =~ s/\s+$//;
    }
}

#and then

trimInPlace(\@re); #Note the \
print OUTFILE join(",", @re), "\n";

またはマップを使用

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

#... the same

while (my @re = $sth->fetchrow_array) {
   print OUTFILE join(",", map { trim($_); } @re), "\n"; #Applies
                                                         #trim() to each element
}

#...

############## subroutines ##################
sub trim { #Don't use prototypes
    my $string = shift;
    $string =~ s/^\s+//;
    $string =~ s/\s+$//;
    return $string;
}

または、$/ を変更して chomp を使用してみてください。これにより、末尾のスペースのみが削除され、それ以上は削除されません。

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

#... the same

my $old_sep = $/;
$/ = " ";
while (my @re = $sth->fetchrow_array) {
   chomp(@re); #Modifies in place, returning number of changes
   print OUTFILE join(",", @re), "\n";
}
$/ = $old_sep;
于 2009-07-08T12:35:08.840 に答える
1

DBD::ODBCがChopBlanks属性をサポートしているかどうかを確認することもできます。

my $dbh = DBI->connect($dbs, $username, $password, { ChopBlanks => 1 } )

ChopBlanks属性は、CHARフィールドの末尾の空白を削除します(つまり、ドライバーがそれをサポートしている場合... DBD :: ODBCがサポートしているかどうかはわかりません)。

于 2009-07-09T01:34:19.043 に答える
0

そのフィールドの末尾に空白があるのはなぜですか? 通常、これはデータベース モデルに何らかの問題があることを示しています。関数に加えてtrim()、データが汚れている理由を調査することもできます。

于 2009-07-10T15:28:29.457 に答える