Re: lug-bg: Perl system() or exec()
- Subject: Re: lug-bg: Perl system() or exec()
- From: Peter Pentchev <roam@xxxxxxxxxxx>
- Date: Mon, 7 Mar 2005 09:50:45 +0200
On Mon, Mar 07, 2005 at 08:20:12AM +0200, Daniel wrote:
> Пиша си аз и стигам до частта, където трябва да риплейсна един стринг в
> текстов файл и то със стандартни инструменти. Написах го с временен файл и
> базирано на sed. Идеята е някаква такава -
> mv file file.tmp;
> sed s/^$something.*$/$somethingandsomethingelse/ file.tmp > file
> rm file.tmp
[snip]
> sed2perl не ме кефи.
Ъъъъъъъъъъъъ... извинявай за *много* глупавия въпрос, но... защо
всъщност е нужно sed или sed2perl изобщо? При работа с *текстови*
файлове и изпълнение на операции по търсене и замяна на регулярни
изрази... аз съм малък и не разбирам, ама не е ли това *основната* идея,
която Лари Уол е имал преди толкова години, за да започне изобщо
разработката на Perl?
В смисъл.... какво не ти харесва в решение на два-три реда:
open(INFILE, '<', $infile) or die "Opening $infile: $!\n";
$tmpfile = "$outfile.tmp";
open(OUTFILE, '>', $tmpfile) or die "Opening $tmpfile: $!\n";
while (<INFILE>) {
s/^$something.*$/$somethingandsomethingelse/;
print OUTFILE;
}
close INFILE;
close OUTFILE;
rename $tmpfile, $outfile or die "Renaming to $outfile: $!\n";
Но виж малко по-долу за File::Temp :)
[връщаме се на sed]
> Това работи, пишейки го на ръка, но слагайки го в system() пищи.
Аррррргх.... ау ау ау ау :(((( По принцип system() е един от по-лошите
начини да изпълняваш каквито и да е външни команди. В допълнение
system() е един от най-лошите начини да изпълняваш команди с параметри,
за които не си сигурен дали в тях има shell metacharacters (символи,
които шелът, през който system() минава, ще третира по специален начин).
А в крайна сметка system() е направо невъзможен начин да изпълняваш
команди, в които *знаеш*, че ще участват shell metacharacters...
По принцип system() *винаги* подава нещата на shell-а (в 99% от случаите
/bin/sh; всъщност под Unix в 100% от случаите /bin/sh), който след това
решава какво да ги прави. Начинът да подадеш нещо на Bourne shell - а
всъщност на който и да е shell - и да си сигурен точно как той ще
интерпретира всичките escape-вания, всички специални символи, кои ще
реши да използва, кои backslashes ще махне, кои символи просто ще
игнорира и всякакви такива неща, в общия случай е да не си правиш труда
:( Няма да стане, или поне няма да стане универсално.
По принцип.... ако *много* настояваш да го направиш по такъв начин, това
може да стане с малко сложна конструкция:
open(INFILE, '<', $infile) or die "Opening $infile: $!\n";
open(OUTFILE, '>', $tmpfile) or die "Opening $tmpfile: $!\n";
$pid = open(SEDPIPE, '-|') or die "forking: $!";
if ($pid == 0) {
# тук малко пренасочване на файлови дескриптори, за да докараш
# INFILE на STDIN, за което не си спомням offhand как ставаше точно
# на Perl
exec('/usr/bin/sed', "s/^$something.*\$/$somethingelse/");
die("executing sed: $!\n");
} else {
while (<SEDPIPE>) {
print OUTFILE;
}
# или дори print OUTFILE while <SEDPIPE>;
}
close OUTFILE;
close INFILE;
rename $tmpfile, $outfile or die "renaming: $!\n";
Но все пак... ако така и така работиш с Perl, тогава няма - повтарям -
НЯМА причина да не ползваш това, за което Perl всъщност *е измислен*
:))) Като допълнителен бонус можеш да получиш това, че в зависимост от
това откъде ти идват данните, може изобщо да не пишеш в infile, ами
директно да си взимаш отнякъде данните, да правиш върху тях по едно s///
и да ги хвърляш във временния файл. А освен това може да е добре да
отделиш минутка, за да разучиш различните функции, предлагани от модула
File::Temp за създаване на временни файлове с уникални имена - в общия
случай $outfile.tmp е огромен security *и* reliability риск, ако се
изхитриш по някакъв начин да пуснеш програмата си два пъти едновременно.
Поздрави,
Петър
--
Peter Pentchev roam@xxxxxxxxxxx roam@xxxxxxxx roam@xxxxxxxxxxx
PGP key: http://people.FreeBSD.org/~roam/roam.key.asc
Key fingerprint FDBA FD79 C26F 3C51 C95E DF9E ED18 B68D 1619 4553
If I had finished this sentence,
Attachment:
pgpIIQCzm8FON.pgp
Description: PGP signature
|