Я пытаюсь прочитать данные из базы данных SQL Server с помощью Perl и модуля DBI. Я намерен прочитать данные и распечатать их в текстовом файле (через запятую). Когда я это делаю, я получаю такой результат:

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

Таким образом, между данными второй переменной и запятой есть пробел. Я попытался обрезать это, используя приведенный ниже код, но это не сработало. Как мне изменить свой код, чтобы избавиться от этих пробелов?

Мой код здесь:

#!/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;
}
3
rjuuser 8 Июл 2009 в 16:28
Вы новичок, поэтому я расскажу вам о стандартном этикете SO: 1. - Проголосуйте за и принимайте ответы, особенно если они те, что вы хотели (отрицательные ответы) 2. - Измените свой вопрос вместо того, чтобы добавлять ответы, это не Форум. Рад, что это сработало!
 – 
Vinko Vrsalovic♦
8 Июл 2009 в 17:14
Вторя Винко, я предлагаю вам принять его ответ и удалить все ответы, которые вы отправили в качестве ответов.
 – 
Sinan Ünür
9 Июл 2009 в 01:56

3 ответа

Лучший ответ

Ваша функция 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;
5
Vinko Vrsalovic 19 Ноя 2012 в 22:24
TrimInPlace не работал по какой-то причине (не было времени проверить почему). Массив внутри функции обрезается, но снаружи это не влияет. trimArray работает хорошо.
 – 
Asaf Mesika
24 Май 2011 в 11:57
TrimInPlace работает с локальной копией @arr, должен работать с @$arrRef: … my $arrRef = shift; for my $val (@$arrRef) { $val =~ s/\s+$//; }
 – 
tstrit
19 Ноя 2012 в 20:23

Вы также можете проверить, поддерживает ли DBD :: ODBC атрибут ChopBlanks:

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

Атрибут ChopBlanks обрезает конечные пробелы в любых полях CHAR (то есть, если ваш драйвер поддерживает его ... Я не уверен, поддерживает ли DBD :: ODBC).

1
derby 9 Июл 2009 в 05:34
DBD :: ODBC поддерживает ChopBlanks, если столбец является символом. Если это не сработает, пришлите мне пример, и я посмотрю на него.
 – 
bohica
20 Ноя 2012 в 13:03

Почему в этом поле есть завершающий пробел? Обычно это указывает на какую-то проблему с моделью базы данных. Помимо функции trim(), вы можете выяснить, почему данные грязные.

0
brian d foy 7 Янв 2013 в 13:14
Столбцы char (N) в MS SQL Server возвращаются как N символов, даже если вы вставили только NM символов. Если вы не хотите использовать столбцы varchar.
 – 
bohica
20 Ноя 2012 в 13:08