2015-07-09 3 views
0

От одного из наших поставщиков я получил DVD с изображениями 12K +. Прежде чем я разместил их на нашем веб-сервере, мне нужно изменить размер, переименовать и скопировать их. Для этого я пишу программу PHP cli. И кажется, что я немного застрял с этим ...Манипулировать массивными массивами строк

Все файлы подходят для определенного шаблона.

Копирование и переименование не являются проблемой, манипуляции с строками.

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

Исходный массив выглядит следующим образом:

$names = array (
'FIX1_VARA_000.1111_FIX2', 
'FIX1_VARB_000.1111.2_FIX2', 
'FIX1_VARB_222.2582_FIX2', 
'FIX1_VARC_555.8794_FIX2', 
'FIX1_VARD_111.0X00(2-5)_FIX2', 
'FIX1_VARA_112.01XX(09-13)_FIX2', 
'FIX1_VARB_444.XXX1(203-207).2_FIX2'  
); 

Каждая строка в массиве начинается с одной и той же фиксированной части в передней части и заканчивается одной и той же фиксированной части в конце FIX1 & fix2 соответственно. После FIX1 всегда есть символ подчеркивания, за которым следует переменная часть, а затем символ подчеркивания. Меня не интересуют неподвижные детали или переменные детали. Поэтому я все это отрезал.

Оставшаяся строка может быть двух типов: Если она содержит только числа и точки: тогда это допустимая строка, и я положил ее в массив $ clean. EG: 000.1111 или 000.111.2 Если строка содержит не только числа и точки в ней, она всегда имеет несколько X в ней и открытую закрытую, заключенную с цифрами, и a. Как 444.XXX1 (203-207) .2

Номера между скобками образуют серию, и каждое число в этой серии должно заменить X. Строки, которые должны быть помещены в $ чистого массива:

444.2031.2

444.2041.2

444.2051.2

444.2061.2

444.2071.2

Это та часть, с которой я борюсь.

$clean = array(); 
foreach ($names as $name){ 
    $item = trim(strstr(str_replace(array('FIX1_', '_FIX2'),'',$name), '_'),'_'); 
    // $item get the values: 
    /* 
    * 000.1111, 
    * 000.1111.2, 
    * 222.2582, 
    * 555.8794, 
    * 111.0X00(2-5), 
    * 112.01XX(09-13), 
    * 444.XXX1(203-207).2 
    * 
    */ 

    // IF an item has no X in it, it can be put in the $clean array 
    if (strpos($item,'X') === false){ 
     //this is true for the first 4 array values in the example 
     $clean[] = $item; 
    } 
    else { 
     //this is for the last 3 array values in the example 
     $b = strpos($item,'('); 
     $e = strpos($item,')'); 
     $sequence = substr($item,$b,$e-$b+1); 

     $item = str_replace($sequence,'',$item); 

     /* This is the part were I'm stuck */ 
     /* ------------------------------- */ 
     /* it should get the values in the sequence variable and iterate over them: 
     * 
     * So for $names[5] ('FIX1_VARA_112.01XX(09-13)_FIX2') I want the folowing values entered into the $clean array: 
     * Value of $sequence = '(09-13)' 
     * 
     * 112.0109 
     * 112.0110 
     * 112.0111 
     * 112.0112 
     * 112.0113 
     * 
     */  
    } 
} 

//NOW ECHO ALL VALUES IN $clean: 
foreach ($clean as $c){ 
    echo $c . "\n"; 
} 

Конечный результат должен быть:

000.1111 
000.1111.2 
222.2582 
555.8794 
111.0200 
111.0300 
111.0400 
111.0500 
112.0109 
112.0110 
112.0111 
112.0112 
112.0113 
444.2031.2 
444.2041.2 
444.2051.2 
444.2061.2 
444.2071.2 

Любая помощь с «Вот я застрял» часть будет весьма признателен.

+0

12k не массивный. Кстати, есть сотни готовых к использованию классов ... –

+2

Будьте осторожны с 'strpos ($ item, 'X') == false', вы должны использовать' === ', в противном случае позиция' 0' будет считаться 'false', так как' 0 == false' – Random

+0

Вы можете просто разбить строки на массив, используя '_' в качестве разделителя и взять третью часть – frz3993

ответ

1

Как @ stdob-- упоминалось, регулярные выражения на самом деле то, что вы хотите. Вот рабочая версия кода:

$names = array (
'FIX1_VARA_000.1111_FIX2', 
'FIX1_VARB_000.1111.2_FIX2', 
'FIX1_VARB_222.2582_FIX2', 
'FIX1_VARC_555.8794_FIX2', 
'FIX1_VARD_111.0X00(2-5)_FIX2', 
'FIX1_VARA_112.01XX(09-13)_FIX2', 
'FIX1_VARB_444.XXX1(203-207).2_FIX2' 
); 

$clean = array(); 
foreach ($names as $name){ 
    $item = trim(strstr(str_replace(array('FIX1_', '_FIX2'),'',$name), '_'),'_'); 
    // $item get the values: 
    /* 
    * 000.1111, 
    * 000.1111.2, 
    * 222.2582, 
    * 555.8794, 
    * 111.0X00(2-5), 
    * 112.01XX(09-13), 
    * 444.XXX1(203-207).2 
    * 
    */ 

    // IF an item has no X in it, it can be put in the $clean array 
    if (strpos($item,'X') === false){ 
     //this is true for the first 4 array values in the example 
     $clean[] = $item; 
    } 
    else { 
     // Initialize the empty matches array (I prefer [] to array(), but pick your poison) 
     $matches = []; 

     // Check out: https://www.regex101.com/r/qG4jS4/1 to see visually how this works (also, regex101.com is just rad) 
     // This uses capture groups, which get stored in the $matches array. 
     preg_match('/\((\d*)-(\d*)\)/', $item, $matches); 

     // Now we've got the array of values that we want to have in our clean array 
     $range = range($matches[1], $matches[2]); 

     // Since preg_match has our parenthesis and digits grabbed for us, get rid of those from the string 
     $item = str_replace($matches[0],'',$item); 


     // Truly regrettable variable names, but you get the idea! 
     foreach($range as $number){ 
      // Here's where it gets ugly. You're wanting the numbers to work like strings (have consistent length 
      // like 09 and 13) but also work like numbers (when you create a sequence of numbers). That kind of 
      // thinking begets hackery. This probably isn't your fault, but it seems helpful to point out. 

      // Anyways, we can use the number of X's in the string to figure out how many characters we ought 
      // to be adding. This is important because otherwise we'll end up with 112.019 instead of 112.0109. 
      // PHP casts that '09' to (int) 9 when we run the range() function, so we lose the leading zero. 
      $xCount = substr_count($item, 'X'); 

      if($xCount > strlen($number)){ 
       // This function adds a given number ($xCount, in our case) of a character ('0') to 
       // the end of a string (unless it's given the STR_PAD_LEFT flag, in which case it adds 
       // the padding to the left side) 
       $number = str_pad($number, $xCount, '0', STR_PAD_LEFT); 
      } 

      // With a quick cheat by padding an empty string with the same number of X's we counted earlier... 
      $xString = str_pad('', $xCount, 'X'); 

      // Now we can add the fixed string into the clean array. 
      $clean[] = str_replace($xString, $number, $item); 
     } 
    } 
} 

// I also happen to prefer var_dump to echo, but again, your mileage may vary. 
var_dump($clean); 

Он выводит:

array (size=18) 
    0 => string '000.1111' (length=8) 
    1 => string '000.1111.2' (length=10) 
    2 => string '222.2582' (length=8) 
    3 => string '555.8794' (length=8) 
    4 => string '111.0200' (length=8) 
    5 => string '111.0300' (length=8) 
    6 => string '111.0400' (length=8) 
    7 => string '111.0500' (length=8) 
    8 => string '112.0109' (length=8) 
    9 => string '112.0110' (length=8) 
    10 => string '112.0111' (length=8) 
    11 => string '112.0112' (length=8) 
    12 => string '112.0113' (length=8) 
    13 => string '444.2031.2' (length=10) 
    14 => string '444.2041.2' (length=10) 
    15 => string '444.2051.2' (length=10) 
    16 => string '444.2061.2' (length=10) 
    17 => string '444.2071.2' (length=10) 

 

--Edit-- Удалены мое предупреждение о strpos и ==, похоже, кто-то уже отметил, что из в комментариях.

1

Во-первых, я полагаю, все ваши файлы имеют действительные шаблоны, так что ни один файл не имеет что-то неправильно в нем, в противном случае, просто добавьте условия безопасности ...
в $sequence, вы получите (09-13). Чтобы использовать цифры, вы должны удалить ( и ), поэтому сделать другую переменную:

$range = substr($item,$b,$e-$b+1); 
// you get '09-13' 

, то вам нужно разбить его:

list($min, $max) = explode("-",$range); 
// $min = '09', $max = '13' 
$nbDigits = strlen($max); 
// $nbDigits = 2 

Тогда вам нужны все цифры от мин до макс:

$numbersList = array(); 
$min = (int)$min; // $min becomes 9, instead of '09' 
$max = (int)$max; 
for($i=(int)$min; $i<=(int)$max; $i++) { 
    // set a number, including leading zeros 
    $numbersList[] = str_pad($i, $nbDigits, '0', STR_PAD_LEFT); 
} 

Тогда вы должны генерировать имена файлов с этими цифрами:

$xPlace = strpos($item,'X'); 
foreach($numbersList as $number) { 
    $filename = $item; 
    for($i=0; $i<$nbDigits; $i++) { 
     // replacing one digit at a time, to replace each 'X' 
     $filename[$xPlace+$i] = $number[$i]; 
    } 
    $clean[] = $filename; 
} 

Он должен сделать какую-то работу, там могут быть некоторые ошибки, но это хорошее начало, дайте ему попробовать :)

Смежные вопросы