Linux-Bulgaria.ORG
навигация

 

начало

пощенски списък

архив на групата

семинари ...

документи

как да ...

 

 

Предишно писмо Следващо писмо Предишно по тема Следващо по тема По Дата По тема (thread)

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



 

наши приятели

 

линукс за българи
http://linux-bg.org

FSA-BG
http://fsa-bg.org

OpenFest
http://openfest.org

FreeBSD BG
http://bg-freebsd.org

KDE-BG
http://kde.fsa-bg.org/

Gnome-BG
http://gnome.cult.bg/

проект OpenFMI
http://openfmi.net

NetField Forum
http://netField.ludost.net/forum/

 

 

Linux-Bulgaria.ORG

Mailing list messages are © Copyright their authors.