2013-04-09 7 views
3

У меня есть программа, которая извлекает данные из ряда других файлов в один большой (~ 200MB) Bulk SQL оператора вставкиЗаменить последний символ в большом файле

INSERT INTO ... 
VALUES 
('a','b',1,2,3), 
('c','d',4,5,6), 

К сожалению, последняя линия должна закончиться на запятой вместо запятой. Есть ли способ (идеально в моей программе perl) превращать только последний символ из , в ;?

Что я пробовал:

1) После того, как файл был закончен и закрыт:

open(DAT,">>$output") || die("Cannot Open File"); 
seek(DAT, 2, SEEK_END); 
print DAT ";"; 
close(DAT); 

Это просто ставит точку с запятой в самом конце.

2) Вызов `perl -p -i -e 's/,$/;/g' $output`; из моей программы perl, но это заменяет каждую запятую.

3) При печати последней строки заканчивайте точкой с запятой вместо запятой. Это не работает, потому что я действительно не знаю, что это была последняя строка, пока строка не была написана.

4) Скопируйте весь файл в новый файл, за исключением последнего символа: ; вместо ,. Однако это медленное и, следовательно, не идеальное.

+0

Вы противоположна модулей CPAN? – squiguy

+0

К сожалению, да. Он работает на внешнем сервере с довольно жесткими ограничениями установки. Не уверены, какие модули будут доступны. Не лучшая окружающая среда. – AlexQueue

ответ

4

Если вы знаете, что «» вы заменяете всегда собираетесь быть вторыми последними байтами в файле (последние байты будучи „\ п“), то вы можете попробовать это:

my $fsize = -s $filename; 
# print $size."\n"; 
open($FILE, "+<", $filename) or die $!; 
seek $FILE, $size-2, SEEK_SET; 
print $FILE ";"; 
close $FILE; 
+0

Отлично работает, за исключением того, что он дает предупреждение «Аргумент« SEEK_SET »не является числовым в поиске в строке app.pl 55.' Долгое время, хотя это работает, я счастлив. – AlexQueue

+0

@AlexQueue вы можете заменить SEEK_SET номером 0. – imran

+1

@AlexQueue или добавить 'use Fcntl;' для импорта этого определения. Или используйте 2 (или SEEK_END) и отрицательную позицию, тогда вам не нужно фиксировать размер файла раньше. – sidyll

1

Вы пытались

perl -p -i -e 's/,$/;/g' 

Какой будет применять эту замену в каждой строке в файле. Чтобы сделать это только один раз, чавкать файл с помощью переключателя -0:

perl -0777 -pi -e 's/,$/;/' 

Это будет соответствовать только если последний символ запятой (с опциональным символ новой строки). Если у вас есть пробелы или другие символы, это не сработает.

+0

Это отлично работает с терминалом, но не из моей программы Perl. Не огромная проблема, но это означает, что принятый ответ был немного легче работать. – AlexQueue

0

Вы используете смещение Wron. SEEK_END добавляет (!) Смещение в позицию END. Поэтому используйте «-2» в качестве смещения. Попробуйте это:

use strict; 
use warnings; 

open my $fh, "+<x.txt" or die; 
seek $fh, -2, 2; 
print $fh ";\n"; 
close $fh; 

Или немного более разговорчивым:

use strict; 
use warnings; 
use Fcntl qw(SEEK_END); 

open my $fh, "+<x.txt" or die; 
seek $fh, -2, SEEK_END; 
print $fh ";\n"; 
close $fh;