LINUX.ORG.RU

Perl переход к строке в файле

 , ,


0

2

Доброго времени суток. Потратил около получаса на поиски нужной функции в интернетах, решил обратиться к нейронному гуглу. Может ли кто-нибудь подсказать, как, открыв файл, начать построчное чтение со строки номер N?

open (STREAM2, 'off.xml') || die "Can't open STREAM2\n";
flock(STREAM2,LONG_NB);
##########################перейти к строке номер $count
while ($curr = <STREAM2>)
{
  ...
};

my $desired_line = 12;
open (STREAM2, 'off.xml') || die "Can't open STREAM2\n";
flock(STREAM2,LONG_NB);
##########################перейти к строке номер $count
while ($curr = <STREAM2>)
{
    next if $. <= $desired_line;
    ...
};
Hoodoo ★★★★★
()
Ответ на: комментарий от default

Инкременирую Tie::File, он специально для этого предназначен.

AITap ★★★★★
()
Ответ на: комментарий от default

у меня в xml около 600 000 структур, каждая от 12 до 18 строк. Если я буду использовать в Tie, оперативы на серве не хватит.

sudo-s
() автор топика
readline for 1..$count;
readline while $. < $count;

и т.д.

arsi ★★★★★
()

так если известен номер строки, то пропустить N итераций вышеприведенного цикла и не париться

EugeneBas ★★
()
Ответ на: комментарий от Hoodoo

А в этом случае мне приходится просматривать первые $desired_line строк. На последних итерациях это более 6-9 миллионов пропусков, что превысит время, за которое сайт отваливается по таймауту.

sudo-s
() автор топика
Ответ на: комментарий от default

Видимо, эта строчка от меня ускользнула, чтож, спасибо, попробую.

sudo-s
() автор топика
Ответ на: комментарий от sudo-s

> А в этом случае мне приходится просматривать первые $desired_line строк.

а как ты себе представляешь моментальное определение позиции произвольной строки файла, не перебрав все предыдущие и не используя файл индексов?

arsi ★★★★★
()
Ответ на: комментарий от sudo-s

> наивно надеюсь на наличие волшебного параметра в open...

ок. как, с твоей точки зрения, open должен позиционироваться на заданную строку, не просматривая файл с самого начала и до искомой строки?

arsi ★★★★★
()

sudo-s

Это все хорошо, но какое будет в этом (использование Tie::File) случае условие выхода? Т.е. если я раньше ставил предусловие цикла, что очередная строка не undef, то как оно будет выглядеть теперь?

tie @array, 'Tie::File', 'off.xml';
while ()# <=== вот здесь
{
  $curr = $array[$lin];
  open (LIN, '>line.txt');
  print (LIN, ++$lin);
  close LIN;
  ...
  ...
  ...
};

sudo-s
() автор топика
#!/usr/bin/perl

use Modern::Perl 2010;

sub readFileNums {
        my ($fileName, $begin, $end) = @_;
        die if ($begin > $end); ## можно реверз сделать
        my $cur = 1; ## см 1
        open (IN, $fileName) || die;

        while ($cur < $begin) { # см 1
                <IN>;
                ++$cur;
        }

        sub {
                if (!wantarray) {
                        return if $cur == ($end + 1); # [1] тут реши сам строки с 0 или с 1
                        ++$cur;
                        <IN>;
                } else {
                        my @text;
                        while (defined (my $str = <IN>) and ($cur++ <= $end)) { ## как и тут
                                push @text => $str;
                        }
                        @text;
                }
        }
}


my $it = readFileNums "test.txt", 3, 10;
#while (my $t = $it->()) {
#       print $t
#}

print $it->();

Вот, няша, бери итератор, работает, как и в списочном, так и скалярном контексте. Проверил - работает. Господа могут найти случаи когда падает или как улучшить. (use Modern::Perl 2010 можешь убрать это замена use strict; warnings еще что-то)

anonymous
()
Ответ на: комментарий от sudo-s

А можно исходную задачу? ИМХО, перезаписывать ещё один файл на каждой строке файла - несколько нерационально.

Кто мешает использовать ту же проверку defined?

Кстати, может быть, $#array будет достаточно быстрым, чтобы использовать его?

AITap ★★★★★
()
Ответ на: комментарий от sudo-s

В таком случае советую пользоваться потоковым парсером XML, а не городить велосипеды. Обычного XML::Twig (A perl module for processing huge XML documents in tree mode) достаточно.

outtaspace ★★★
()
Ответ на: комментарий от AITap

Задача такова: имеется xml-файл невероятных размеров, подгружаемый втихаря на сервер по фтп. Содержимое примерно такое:

<?xml version="1.0" encoding="windows-1251"?>
<!DOCTYPE yml_catalog SYSTEM "shops.dtd">
<yml_catalog date="2010-10-05 23:21">
  <shop>
    <name>OZON.ru</name>
    <company>ООО "Интернет Решения"</company>
    <url>http://www.ozon.ru/</url>
    <currencies>
      <currency id="RUR" rate="1" />
    </currencies>
    <categories>
      <category id="8108">Художественная литература</category>
      <category id="12351" parentId="8108">Русская литература</category>
      <category id="1113586" parentId="12351">Юбилей А.П. Чехова! К 150-летию со дня рождения</category>
      <category id="1000362" parentId="12351">Современная русская литература (с 1991 года)</category>
      <category id="1071049" parentId="1000362">Женская проза</category>
      <category id="1087320" parentId="1071049">Борминская, Светлана</category>
      <category id="1087321" parentId="1071049">Ким, Лилия</category>
      <category id="1092308" parentId="1071049">Лазорева, Ольга</category>
      <category id="1072180" parentId="1071049">Латынина, Юлия</category>
      <category id="1071241" parentId="1071049">Петрушевская, Людмила</category>
      <category id="1099220" parentId="1071049">Робски, Оксана</category>
      <category id="1071239" parentId="1071049">Рубина, Дина</category>
      <category id="1099221" parentId="1071049">Славникова, Ольга</category>
      <category id="1118376" parentId="1071049">Соломатина, Татьяна</category>
...
...
...
</categories>

<offers>
      <offer id="76276" type="artist.title" available="false">
        <url>http://www.ozon.ru/context/detail/id/76276/?from=partner</url>
        <price>323</price>
        <currencyId>RUR</currencyId>
        <categoryId>1093871</categoryId>
        <categoryId>1098207</categoryId>
        <picture>http://www.ozon.ru/multimedia/audio_cd_covers/cdm254_11_10.jpg</picture>
        <delivery>true</delivery>
        <orderingTime>
          <ordering>В течение недели</ordering>
        </orderingTime>
        <artist>Иосиф Бродский</artist>
        <title>Иосиф Бродский. Ранние стихотворения</title>
        <year>1996</year>
        <media>Audio CD</media>
        <description>Ночной полет; Дни бегут надо мной…; Как тюремный засов…</description>
      </offer>
      <offer id="83061" type="book" available="false">
        <url>http://www.ozon.ru/context/detail/id/83061/?from=partner</url>
        <price>109</price>
        <currencyId>RUR</currencyId>
        <categoryId>1072967</categoryId>
        <picture>http://www.ozon.ru/multimedia/books_covers/fo223_06_07.jpg</picture>
        <delivery>true</delivery>
        <orderingTime>
          <ordering>В течение недели</ordering>
        </orderingTime>
        <author>В. С. Левадный</author>
        <name>Ремонт квартиры в современных условиях</name>
        <publisher>Аделант</publisher>
        <series>Своими руками</series>
        <year>2007</year>
        <ISBN>5-89691-024-X</ISBN>
        <binding>84x108/32</binding>
        <page_extent>384</page_extent>
        <table_of_contents>Ремонт квартиры в современных условиях</table_of_contents>
        <description>Книга посвящена особенностям ремонта квартиры с применением современных инструментов и материалов, задействованию новых технологий при осуществлении перепланировки внутриквартирного пространства, отделке и восстановлению покрытий и стен, потолков, пола, ремонту лестниц, электро- и сантехнического оборудования, оборудованию вентиляции.</description>
      </offer>
...
...
...
    </offers>
  </shop>
</yml_catalog>

Необходимо создать 2 таблицы в базе на mysql, в первой параметры каждой из категории, потом создать таблицу с параметрами товаров. Фишка в том, что поля таблицы товаров меняются от товара к товару, ввиду чего изначально высасываются все уникальные теги, из них формируется запрос. Уже написан сплиттер, который бьет первый файл надвое - первый кусок с категориями, второй - с товарами. Есть INSERT-скрипт, который забивает в таблицу категорий значения из парсера первого куска. Дальше следующий скрипт выбирает уникальные теги, делает таблицу со всеми возможными полями. Теперь остается только засовывать в нужные столбцы нужные значения, но в файле столько товаров (в тестовом порядка 570к), что сайт, который вызывает скрипт, отваливается по таймауту в браузере, а на серваке процесс перла неустанно продолжает пахать. В целом, он отлично справляется, но...

Велено переделать так, чтобы он отправлял по 8000 запросов за раз, перезагружался (счетчик таймаута обнулялся) и отправлял следующие 8к товаров в базу.

sudo-s
() автор топика
Ответ на: комментарий от outtaspace

тут в том и соль, что надо вообще все руками сделать. такой вот занимательный велосипедный завод.

sudo-s
() автор топика

Видимо, умнее, чем использовать XML::Twig и переписать весь велосипед ничего не найдется...

sudo-s
() автор топика
Ответ на: комментарий от outtaspace

ну вообще мы просто «письками меряемся»

sudo-s
() автор топика
Ответ на: комментарий от sudo-s

А что делать, если Twig перестанет укладываться в таймаут?

Может быть, изначально форкаться и работать в фоне?

AITap ★★★★★
()

Я бы начал с изменения архитектуры: (1) браузер вызывает callback на стороне сервера (2) callback записывает в БД, в locks, параметры job (3) при обновлении locks срабатывает триггер отправляющий перловому воркеру запрос (4) воркер при завершении работы удаляет job из locks

Ну а офисный клерк может нажимать F5 в табе браузера и отслеживать статус задачи (ждем когда in progress сменится на success или error).

8*10^3 запросов? Такой пул понадобится если база подтормаживает (облокировки или отключение обновления индексов).

Как уже догадались, это не ответ на вопрос про парсинг. Скорее это совет человеку программирующему в расчете на совпадения.

outtaspace ★★★
()
Ответ на: комментарий от AITap

Я так и сделал. Парсинг и запись в базу лежит в списке процессов на сервере, пока юзверям дают страничку с надписью «Ожидайте» и занимательнейшей флеш-игрой. А когда база забита, просто прерывает веселье пользователя и выдает краткий отчет.

sudo-s
() автор топика
Ответ на: комментарий от sudo-s

Если важна скорость, то попробуйте писать в базу с отключенным autocommit, или, лучше использовать COPY

disarmer ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.