Четене на файл с php и взимане на редове между други редове

Pok4

Registered
Здравейте,
Искам да парсна един текстов файл за Му онлайн става дума. Целта ми е да взема всички редове между други. Ето пример:
PHP:
13
//Type
shest
pet
chetiri
end

6
//Type
sedem
osem
devet
end
Искам да взема всичко между:
13
//Type
и end
и
6
//Type
и end
Имам една функция get_string_between и тя не работи в случая. Като взема всичко между тези редове аз ще се оправя.. Там вече мога да ползвам str_contains или strpos и да си взема инфо за всеки ред. Просто се чудя как да взема редовете между тези по-горе..
Имате ли идея как да стане това?
Пробвах с get_string_between($lines,"13\n//Type","end"), но не става..
 
Да.
 
PHP:
$text = '13
//Type
shest
pet
chetiri
end

6
//Type
sedem
osem
devet
end';
$keys = ['13', '//Type', '6'];
$text = explode("\n", $text);
foreach ($text as $key => $value) {
    if(!in_array($value, $keys)) {
        $collect[] = $value;
    }
}
 
Ще пиша след работа, че снощи беше късно. Тествах го, но няма да свърши работа.
Извинявам се, ако съм те подвел и съм ти загубил времето.
Това е файла - https://pastebin.com/s6JN5wSa
Аз ще проуча по-подробно и ще дам решение, когато съм готов.
 
PHP:
<?php

// The string to parse
$var = '0
//Type   Slot   Skill   Width   Height   HaveSerial   HaveOption   DropItem   Name                                 
0        0      0       1       2        1            1            1          "Kris"                               
1        0      0       1       3        1            1            1          "Short Sword"                        
2        0      0       1       3        1            1            1          "Rapier"                             
end

1
//Type   Slot   Skill   Width   Height   HaveSerial   HaveOption   DropItem   Name                                 
0        0      0       1       3        1            1            1          "Small Axe"                          
1        0      0       1       3        1            1            1          "Hand Axe"                           
2        0      19      1       3        1            1            1          "Double Axe"                         
8        0      19      2       3        1            1            1          "Crescent Axe"                       
end';

// Split the string by line breaks
$lines = explode("\n", $var);

// Find the lines between "//Type" and "end"
$data_lines = array();
$found = false;
foreach ($lines as $line) {
    if (strpos($line, "//Type") !== false) {
        $found = true;
        continue;
    }
    if (strpos($line, "end") !== false) {
        $found = false;
        continue;
    }
    if ($found) {
        $data_lines[] = $line;
    }
}

// Output the resulting array
print_r($data_lines);

Като прочетеш файла с file_get_contents би трябвало да работи с всички данни :) :)
 
Последно редактирано:
Целта е да прихваща 0-та и 1-цата над //Type, понеже по тях ще се търси.
13
//Type
.. Redove...
end
И трябва да се търси по 13 //Type. Ако не чете с новия ред след 13,може някак //Type да се премести отгоре и да стане 13//Type,а не да е както сега:
13
//Type..
При условие, че не се пипа по файла.

Благодаря за отделеното време.
 
Последно редактирано:
Най-простото решение.

PHP:
<?php

$lines = file('test.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);

$parsed = [];
$index = 0;

$i = 0;
while($i < count($lines)) {
    $line = $lines[$i];
    if (is_numeric($line)) {
        $index = $line;
        $i += 2;
        continue;
    }
    
    if (strpos($line, "end") === 0) {
        $i++;
        continue;
    }
    
    $parsed[$index][] = $line;
    $i++;
}

var_dump($parsed);


Файла като цяло е доста "счупен" (така да се каже) и четенето му не порядъчно, ако трябва да се правят по-сериозни парсвания.
 
Лошо, хора :)
Някои айтъми имат 'end' в имената и ще се дъни. Не знам какво да правя, май както е сега с mysql вариант си е най-добре и от там да чете. Там са всички предмети описани и така работи... Търсих за готови варианти, но няма.. Явно който и да се е пробвал е ударил на камък. Има една система, която чете от файла, но е много голяма и не мога да ровя в нея да търся.. прекалено е голяма и много хардкодната..
 
Ми не знам, но вариантите дадени тук нещо не вадят точното инфо. Нямам време, Събота и Неделя ще тествам по-обстойно и ще пиша пак.
Благодаря за примерите, които дадохте. Оценявам го!
Ще тествам тогава и аз по-добре, но @Revelation твоя код с 13 като индекс вадеше неточни резултати. Може и да не съм обяснил какво точно искам (като се замисля).
Много ми е натоварено и работя по няколко неща след работа и нямам време..
 
Ами кода е по това, което си дал като обяснение. Естествено, няма да седна да си играя да проверявам изцяло валидността на резултата. И като цяло между 12 и 13 имаш нестандартна част във файла, която вероятно е причината да получаваш грешни резултати.

Както казах, формата на файла не е порядъчен и има доста изключения, което е проблем, защото утре може да дойдеш с друг файл, който има други форматни различия и да кажеш, че кода, който сме дали не работи.

Ако искаш нещо по конкретно дай примери с оригиналния файл и дай няколко файла, които имат потенциални различия.
 
Прегледай примера да разбереш как да го ползваш

PHP:
<?php

class ItemGroup
{
    private int $id;

    /**
     * @var stdClass[]
     */
    private array $items;

    public function __construct(int $id, array $items)
    {
        $this->id = $id;
        $this->items = $items;
    }

    public function getId(): int
    {
        return $this->id;
    }

    public function getItems(): array
    {
        return $this->items;
    }
}

class Entry
{
    private string $content;

    public function __construct(string $content)
    {
        $this->content = trim($content);
    }

    public function getGroupId(): int
    {
        return (int) $this->content;
    }

    public function isGroupId(): bool
    {
        return is_numeric($this->content);
    }

    public function getHeader(): array
    {
        $header = preg_split("/\s+/", $this->content);
        $header[0] = substr($header[0], 2); // Remove slashes: //Type -> Type

        return $header;
    }

    public function isHeader(): bool
    {
        return str_starts_with($this->content, '//Type');
    }

    public function getItem(): array
    {
        return preg_split("/\"*\s+\s{2}\"*/", $this->content);
    }

    public function isItem(): bool
    {
        return !($this->isEmpty() ||
            $this->isGroupId() ||
            $this->isComment() ||
            $this->isHeader() ||
            $this->isEndOfGroup());
    }

    public function isEndOfGroup(): bool
    {
        return $this->content === 'end';
    }

    private function isComment(): bool
    {
        return str_starts_with($this->content, '//') && !$this->isHeader();
    }

    private function isEmpty(): bool
    {
        return strlen($this->content) === 0;
    }
}

class Parser implements Iterator
{
    private array $lines;

    private int $position;

    private function __construct(array $lines)
    {
        $this->lines = $lines;
        $this->position = 0;
    }

    /**
     * @param array $lines
     * @return ItemGroup[]
     */
    public static function parse(array $lines): array
    {
        $parser = new Parser($lines);
        $groups = [];
        $groupId = -1;
        $header = [];
        $items = [];

        foreach ($parser as $entry) {
            if ($entry->isGroupId()) {
                $groupId = $entry->getGroupId();
            } elseif ($entry->isHeader()) {
                $header = $entry->getHeader();
            } elseif ($entry->isItem()) {
                $item = $entry->getItem();
                $obj = new stdClass();
                $items[] = $obj;

                for ($i = 0; $i < count($item); $i++) {
                    $title = $header[$i];
                    $propertyName = strlen($title) > 2 ? lcfirst($title) : strtolower($title);
                    $obj->$propertyName = $item[$i];
                }
            } elseif ($entry->isEndOfGroup()) {
                $groups[] = new ItemGroup($groupId, $items);
                $groupId = -1;
                $header = [];
                $items = [];
            }
        }

        return $groups;
    }

    public function current(): Entry
    {
        return new Entry($this->lines[$this->position]);
    }

    public function next(): void
    {
        $this->position++;
    }

    public function key(): int
    {
        return $this->position;
    }

    public function valid(): bool
    {
        return $this->position > -1 && $this->position < count($this->lines);
    }

    public function rewind(): void
    {
        $this->position = 0;
    }
}

// Example
$groups = Parser::parse(file('items.txt'));

foreach ($groups as $group) {
    echo '<pre>';
    echo 'ID: ' . $group->getId() . '; Items: ' . count($group->getItems()) . "\n";

    foreach ($group->getItems() as $item) {
        echo 'Name: ' . $item->name . '; Level: ' . $item->level . "\n";
    }

    echo '</pre>';
}
 
Супер! Ето това ми трябваше... Сам нямаше да мога да се оправя, сигурен съм.
Сам ли го написа или го намери от някъде ? :)
 

Back
Горе