· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.ZEN —› Вопрос по Perl'у.

. 1 . 2 . >>

Посл.отвђт Сообщенiе


Дата: Июн 21, 2004 01:36:06 · Поправил: Asterix

Лень искать - решил спросить ;-)

Вопрос касательно Perl'а.

Допустим имею я в программе переменные
$temp1='cdcdcdc';
$temp2='bcbcbcbcb';
$temp3='asasasa';



как бы мне организовать обход этих переменных в цикле, если
допустим требуется выполнить
s/$temp//g; # где $temp последовательно должна принимать значения $temp1, $temp2, $temp3


Дата: Июн 21, 2004 05:45:40

Видимо никто из неспящих не знает ;-)
Сам я сделал через список так:
@temp=("cdcdcdc","bcbcbcbcb","asasasa");
$i=0;
while ($i<=2)
 {
   s/$temp[$i]//g;
   $i++;
 }


Дата: Июн 21, 2004 06:29:44

Туплю, так будет правильнее:
@temp=("cdcdcdc","bcbcbcbcb","asasasa");
foreach $i (@temp)
 {
   s/$i//g;
 }


Дата: Июн 21, 2004 18:11:00

Лишь два совета, о великий :)
1) Используй $_, т.к. в этом случае производительность будет выше - перлу не надо будет создавать память для $i.
2) Используй не \"\" в качестве кавычек, а \'\', т.к. в этом случае перл не будет производить ресолвинг строк внутри кавычек, что также поднимет производительность :)
Т.е. переписанный с учетом оптимизации клочок выглядит так:
foreach ('cdcdcdc','bcbcbcbcb','asasasa')
 {
   s/$_//g;
 }




Дата: Июн 21, 2004 21:53:46

volodya

Действительно, я не в восторге от скорости :-(
Вопрос такой, можно ли использовать неявную переменную $_
если код у меня такой(естес-но это кусок):
@BYTE=('BYTE','CHAR','BOOLEAN');

while(<IN>)
{
       foreach $i (@BYTE)
        {
          s/^(\s*)$i\s+([a-zA-Z0-9_]+)\s*;(.*)/$1.$2  db  ?$3/g;
          s/^(\s*)$i\s+([a-zA-Z0-9_]+)\[([0-9]+)\]\s*;(.*)/$1.$2  rb  $3$4/g;
          s/^(\s*)$i\s+([a-zA-Z0-9_]+)\[([\sA-Z0-9_\+\-\*]+)\]\s*;(.*)/$1.$2  rb  $3$4/g;
        }
print OUT $_;
}


Дата: Июн 21, 2004 23:06:31

И опять эта твоя стратегия с заменой... Сами по себе эти регулярки очень медленны. А если ты еще хочешь и s, да еще и со спецификатором g, то чего же ты ждешь? Медленно это будет и все.
Теперь сугубо по твоему вопросу.
Точный ответ: я не знаю :)
Более расплывчато: у каждой переменной есть своя область видимости (scope по-английски). Так вот, внутри WHILE при foreach у тебя есть scope, и, возможно, $_ в скопе внутри foreach будет одна, а при выходе из foreach будет восстановлена старая $_. Однако это надо проверить. Просто-напросто вставь print в foreach и print в while и погляди, что там к чему :)


Дата: Июн 21, 2004 23:07:44

тогда лучше не читай строку в $_ сделай так:
while ($string = <IN>)
foreach (@BYTE)
{
s/^(\s*)$_\s+([......
........
}

print OUT $string;
хотя не вижу всего алгоритма, думаю, что $string как раз у тебя и разбивается в @BYTE
и не уверен, что это все будет намного быстрее (если вообще будет)


Дата: Июн 21, 2004 23:12:44

Да, и еще. Опять вопрос стиля, но можно пожертвовать в пользу производительности.
Ты пишешь, @BYTE=('BYTE','CHAR','BOOLEAN');
Это неплохо, но перл вынужден создать внутреннюю переменную под массив (тип AV, если тебе любопытно: http://gisle.aas.no/perl/illguts/) и скопировать туда данные. Этого можно избежать, просто написав сие:
foreach ('BYTE','CHAR','BOOLEAN')
{
  #do what you need to do
}


В этом случае программа становится менее понятной, но более быстрой. Чему отдать предпочтение - дело за тобой.


Дата: Июн 21, 2004 23:14:09

Mad_C

Вот это:
while ($string = <IN>) 


хуже, чем это:
while(<IN>)


Asterix сделал все верно. Твой вариант еще медленнее.


Дата: Июн 21, 2004 23:16:31

а ты уже выяснил область видимости $_ ???


Дата: Июн 21, 2004 23:20:52 · Поправил: volodya

Уже да :)
open (IN, 'foo.txt');
while(<IN>)
{
	foreach('BYTE','CHAR','BOOLEAN')
	{
		print;	
	}
	print;	
}
close(IN);


Работает как и предполагалось. $_ восстанавливается по выходу из цикла foreach, что хорошо :)


Дата: Июн 21, 2004 23:22:21

тогда сорри, несомненно так лучше :)))


Дата: Июн 22, 2004 00:53:50

volodya
Нет, нифига не получилось :-( Скрипт в таком виде(ниже) перестал работать, а я хотел сделать цикл не только для BYTE но и для WORD/DWORD и т.д.
#!/usr/bin/perl -w

print("Processing, please wait.\n");

foreach $f (<*.h>)
{
open(IN, "$f") or die "Can't open file: $!";
chop($f);
chop($f);

open(OUT, "+>$f\_.inc") or die "Can't open file out.inc for writing: $!";

while(<IN>)
{
# конвертирование заголовков структур
s/\btypedef\s+(struc)t(\s+)_([a-zA-Z0-9_]+)(.*)/$1$2$3$4/ig;
s/\btypedef\s+(struc)t(\s+)tag([a-zA-Z0-9_]+)(.*)/$1$2$3$4/ig;
s/\btypedef\s+(struc)t(\s+)([a-zA-Z0-9_]+)(.*)/$1$2$3$4/ig;

#    конвертирование параметров структур
#    8 bit BYTE
       foreach('BYTE','CHAR','BOOLEAN')
        {
          s/^(\s*)$_\s+([a-zA-Z0-9_]+)\s*;(.*)/$1.$2  db  ?$3/g;
          s/^(\s*)$_\s+([a-zA-Z0-9_]+)\[([0-9]+)\]\s*;(.*)/$1.$2  rb  $3$4/g;
          s/^(\s*)$_\s+([a-zA-Z0-9_]+)\[([\sA-Z0-9_\+\-\*]+)\]\s*;(.*)/$1.$2  rb  $3$4/g;
        }
#    16 bit WORD
s/\bWORD\s+([a-zA-Z0-9_]+)\s*;(.*)/.$1  dw  ?$2/ig;
s/\bDWORD\s+([a-zA-Z0-9_]+)\s*;(.*)/.$1  dd  ?$2/ig;
s/\bLONG\s+([a-zA-Z0-9_]+)\s*;(.*)/.$1  dd  ?$2/ig;

s/\bWORD\s+([a-zA-Z0-9_]+)\[([0-9]+)\]\s*;(.*)/.$1  rw  $2$3/ig;
s/\bDWORD\s+([a-zA-Z0-9_]+)\[([0-9]+)\]\s*;(.*)/.$1  rd  $2$3/ig;

s/\bWORD\s+([a-zA-Z0-9_]+)\[([\sA-Z0-9_\+\-\*]+)\]\s*;(.*)/.$1  rw  $2$3/ig;
s/\bDWORD\s+([a-zA-Z0-9_]+)\[([\sA-Z0-9_\+\-\*]+)\]\s*;(.*)/.$1  rd  $2$3/ig;

# конвертирование констант
# десятичных
s/^#define\s+([a-zA-Z0-9_]+)(\s+)([0-9]+\b)(.*)/$1$2=  $3$4/ig;
s/^#define\s+([a-zA-Z0-9_]+)(\s+)\(\s*([0-9]+)\s*\)(.*)/$1$2=  $3$4/ig;

# шестнадцатиричных
s/^#define\s+([a-zA-Z0-9_]+)(\s+)0x([a-fA-F0-9]+\b)(.*)/$1$2=  $3h$4/ig;
s/^#define\s+([a-zA-Z0-9_]+)(\s+)\(\s*0x([a-fA-F0-9]+)\s*\)(.*)/$1$2=  $3h$4/ig;
s/^#define\s+([a-zA-Z0-9_]+)(\s+)\(\s*0x([a-fA-F0-9]+)L\s*\)(.*)/$1$2=   $3h$4/ig;
s/^#define\s+([a-zA-Z0-9_]+)(\s+)\(\s*\(\s*DWORD\s*\)\s*0x([a-fA-F0-9] +)\s*\)(.*)/$1$2=  $3h$4/ig;
s/^#define\s+([a-zA-Z0-9_]+)(\s+)\(\s*\(\s*DWORD\s*\)\s*0x([a-fA-F0-9] +)L\s*\)(.*)/$1$2=  $3h$4/ig;

# конвертирование комментариев, т.е. '//' заменяем на ';'
s/\/\//;/g;

print OUT $_;

}

close(OUT);
close(IN);
}


Дата: Июн 22, 2004 01:00:06

> И опять эта твоя стратегия с заменой...

По другому никак, только регулярки, причём эти у меня ещё не совсем правильны, возможны ложные срабатывания, но постепенно привожу их к нужному виду.


Дата: Июн 22, 2004 01:02:29

По другому никак

Это тебе так только кажется :)

Скрипт в таком виде(ниже) перестал работать

Что значит, перестал работать?
Хочешь, чтобы я тебе тестером работал? :)
Если да - то давай мне входной файл, посмотрю.
Да, как там моя просьба поживает, а?

. 1 . 2 . >>


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.044