PHP несколько подстрок на строку - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть строка, для которой мне предоставлен индекс строки.

Я создаю процесс для его чтения, и мне интересно, существует ли какая-либо функция php, которую я пропустил или не знаю, чтобы выполнить этот процесс гораздо проще.

$ данные:

Invoice No..... Sale Type Desc...... Misc Amt.... Misc Acc.. Misc Acc Desc.....................................

FOCF219611      CUSTOMER                    -0.02 8050       TOOLS & SUPPLIES - SERVICE
FOCF219669      CUSTOMER                   -14.49 8050       TOOLS & SUPPLIES - SERVICE

$ fieldIndexes:

Array (
  [0] => 15 
  [1] => 20 
  [2] => 12 
  [3] => 10
  [4] => 50
)

Разделить $data на $headers массив:

array_push($headers, substr($data, 0, $fieldIndexes[0]));
array_push($headers, substr($data, $fieldIndexes[0], $fieldIndexes[1]));
array_push($headers, substr($data, $fieldIndexes[1], $fieldIndexes[2]));
array_push($headers, substr($data, $fieldIndexes[2], $fieldIndexes[3]));
array_push($headers, substr($data, $fieldIndexes[3], $fieldIndexes[4]));

Есть ли функция, которая может удалить часть строки - например, array_shift для строки? Я думал, что смогу зациклить $fieldIndexes, извлечь первую длину из начала строки и так далее до тех пор, пока строка не станет пустой, сконцентрировать ее в 3 строки и сделать ее переносимой для любого числа fieldIndexes?

Желаемый результат:

Array
(
[HEADERS] => Array
    (
        [0] => Invoice No
        [1] => Sale Type Desc
        [2] => Misc Amt
        [3] => Misc Acc
        [4] => Misc Acc Desc

    )

[1] => Array
    (
        [Invoice No] => FOCF219611
        [Sale Type Desc] => CUSTOMER
        [Misc Amt] => -0.02
        [Misc Acc] => 8050
        [Misc Acc Desc] => TOOLS & SUPPLIES - SERVICE

    )
)                      

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Вы можете создать функцию, подобную этой, для разделения, используя размеры чанков. Примечание. Поскольку каждый размер в массиве $fieldIndexes не содержит пробелов между столбцами, я добавил один к каждой длине (15 + 1, 20 + 1, ...)

<?php

$headerString ="Invoice No..... Sale Type Desc...... Misc Amt.... Misc Acc.. Misc Acc Desc.....................................";
$fieldIndexes = [ 15+1, 20+1, 12+1, 10+1,  50+1];


function getParts($string, $positions){
    $parts = array();

    foreach ($positions as $position){
        $parts[] = substr($string, 0, $position);
        $string = substr($string, $position);
    }

    return $parts;
}

print_r(getParts($headerString, $fieldIndexes));
?>

Результат:

Array
(
    [0] => Invoice No..... 
    [1] => Sale Type Desc...... 
    [2] => Misc Amt.... 
    [3] => Misc Acc.. 
    [4] => Misc Acc Desc.....................................
)
0 голосов
/ 05 сентября 2018

Вот так (потому что я сказал это в комментариях)

$str = 'Invoice No..... Sale Type Desc...... Misc Amt.... Misc Acc.. Misc Acc Desc.....................................';

$f = fopen('php://temp', 'w+');
fwrite($f, $str);
rewind($f);
$headers = [];

$header = '';
while(false !== ($c = fgetc($f))){
    if($c != '.'){
        $header .= $c;
    }elseif(!empty($header)){
        $headers[] = trim($header);
        $header = '';
    }
}

print_r($headers);

Выходы

Array
(
    [0] => Invoice No
    [1] => Sale Type Desc
    [2] => Misc Amt
    [3] => Misc Acc
    [4] => Misc Acc Desc
)

Заметьте, я сделал это без использования смещения, но я упомянул об этом в комментариях, и мне нравится делать странные вещи, подобные этой. Это приятно.

Конечно, вы можете сделать это для того же результата:

$str = 'Invoice No..... Sale Type Desc...... Misc Amt.... Misc Acc.. Misc Acc Desc.....................................';

print_r(array_filter(array_map('trim',explode('.', $str))));

Но это далеко-далеко не просто.

Песочница

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

 print_r(array_values(array_filter(array_map('trim',explode('.', $str)))));

LOL, еще один понедельник.

UPDATE

Вы также можете использовать файл-конвертер потока для исправления файла для чтения в формате CSV. В PHP5.4 (я думаю или 5.3) SplFileObj отсутствует fgetcsv, и я использовал трюк с ними для исправления этого класса ....:)

Это была моя точка зрения (но я многого не знаю)

$str = 'Invoice No..... Sale Type Desc...... Misc Amt.... Misc Acc.. Misc Acc Desc.....................................
somedata .... someother stuff ... foobar ... hello ... world..
';

//pretend this is a real file
$f = fopen('php://temp', 'w+');
fwrite($f, $str);
rewind($f);
$headers = [];
$num_headers = 0;

$i = 1;
while(false !== ($c = fgetcsv($f))){

     //if there is only one element assume the delimiter is wrong
    if(count($c) == 1){
        //you could test the string for multiple delimiters and change
        /*
         if(strpos($c, '.')){
            $regex = '/\.+/'
         }else if(strpos($c, '~')){
            $regex = '/~+/'
         } etc....
        */

        //use memory buffer to fix files with .'s but still read them as
        //a normal CSV file, php://memory is really fast.
        //and this gives us all the parsing benefits of fgetcsv
        //you could use any delimiter here you want.
        $fixed =  trim(preg_replace('/\.+/', ',', $c[0]),',');
        $m = fopen('php://memory', 'w+');
        fwrite($m, $fixed);
        rewind($m);
        $c = fgetcsv($m);
    }
    //trim any spaces, not a bad idea anyway
    $c = array_map('trim', $c);

    //if no headers use the first line of file as the header
    if(empty($headers)){
        $headers = $c;
        //count them (see below)
        $num_headers = count($headers);
        continue;
    }

     //array_combine is a good choice for header => values
     //but the arrays have to be the same size
    if(count($c) != $num_headers) die("missing dilimter on line {$i}");

    $line = array_combine($headers, $c);

    //continue with normal csv opperation
    print_r($line);

    ++$i; //track the line number
}

Выход

Array
(
    [Invoice No] => somedata
    [Sale Type Desc] => someother stuff
    [Misc Amt] => foobar
    [Misc Acc] => hello
    [Misc Acc Desc] => world
)

UPDATE

Как я уже упоминал в комментариях (после выяснения, что это был HTML). Вы можете использовать DOM-парсер. Одна из них, которую я использовал в прошлом, это PHPQuery, она немного устарела. Но это приятно, потому что вы можете использовать синтаксис jQuery. Например, скажем, у вас есть

<ul id="title" >
    <li>header</li>
    <li>header</li>
    <li>header</li>
</ul>

Вы можете найти это с чем-то вроде этого (это было давно, так что если это не так, извините)

  $length =  $PHPQuery->find("#headers li")->lenght;

   for($i=0;$i<$lenght;++$i){
      echo $PHPQuery->find("#headers li:eq($i)")->text();
   }

Вы можете даже получить атрибуты, используя, например, ->attr('href'). По сути, вы можете воспользоваться преимуществами структуры HTML и извлечь то, что вам нужно, вместо того, чтобы конвертировать ее в текст и пытаться удалить кучу «вещей»

Ура!

...