Сценарий пакетной обработки для замены коротких открытых тегов PHP <? php

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

Примечание. Эта функция изменяет ссылки Player в переданных IEnumerable<Player>. Если по какой-либо причине вы не хотите использовать это поведение, просто замените Player = player на Player = new Player { Name = player.Name, Points = player.Points }, чтобы скопировать их.

using System;
using System.Linq;
using System.Collections.Generic;

public static IEnumerable<Player> GetGroupedPlayers(IEnumerable<Player> players)
{
    return players
    .OrderByDescending(player => player.Points)
    .Select((player, index) =>
    new
    {
        Player = player,
        Rank = ++index
    })
    .GroupBy(container => container.Player.Points)
    .Select(group =>
    {
        var firstPlayer = group.First().Player;
        var groupMin = group.Min(container => container.Rank);
        var groupMax = group.Max(container => container.Rank);
        firstPlayer.Rank = groupMin == groupMax ? $"{groupMin}." : $"{groupMin} - {groupMax}.";
        return group.Select(g => g.Player);
    })
    .SelectMany(player => player);
}

Надеюсь, это поможет.

18
задан Benjamin W. 23 March 2016 в 00:32
поделиться

7 ответов

не используйте regexps для парсинга формальных языков - Вы будете всегда сталкиваться со стогами сена, которые Вы не ожидали. как:

<?
$bla = '?> now what? <?';

более безопасно использовать процессор, который знает о структуре языка. для HTML, который был бы xml процессором; для php, встроенного расширения токенизатора. это имеет T_OPEN_TAG маркер синтаксического анализатора, который соответствует <?php, <? или <%, и T_OPEN_TAG_WITH_ECHO, который соответствует <?= или <%=. для замены всех коротких открытых тегов Вы находите все эти маркеры и замену T_OPEN_TAG с <?php и T_OPEN_TAG_WITH_ECHO с <?php echo .

реализацию оставляют как осуществление для читателя :)

РЕДАКТИРОВАНИЕ 1: инспектор манежа был так добр для обеспечения того.

РЕДАКТИРОВАНИЕ 2: в системах с short_open_tag выключенный в php.ini, <?, <%, и <?= не будет распознан заменяющим сценарием. чтобы заставить сценарий работать над такими системами, включить short_open_tag через параметр командной строки:

php -d short_open_tag=On short_open_tag_replacement_script.php

p.s. страница справочника для token_get_all () и googleing для творческих комбинаций токенизатора, token_get_all, и маркерные имена синтаксического анализатора мог бы помочь.

p.p.s. видят, что также Regex для парсинга определяют () содержание, возможное? здесь на ТАК

16
ответ дан 30 November 2019 в 06:51
поделиться

Это типично для страниц XML/XHTML для включения следующего кода:

<?php echo '<?xml version="1.0" encoding="UTF-8" ?>'; ?>

Конечно, это не должно быть изменено ни один на:

<?phpphp echo '<?phpxml version="1.0" encoding="UTF-8" ?>'; ?>

ни:

<?php echo '<?phpxml version="1.0" encoding="UTF-8" ?>'; ?>
0
ответ дан 30 November 2019 в 06:51
поделиться

Я должен был пройти это прежде, и я нашел, что он лучше всего сделал это шаг за шагом. Плохой сценарий, пытающийся поймать все это, может испортить МНОГО файлов.

Я использовал Коду (или любой другой веб-редактор), чтобы сделать, простое находит и заменяет на очень определенных строках.

Например, запуск с"

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

0
ответ дан 30 November 2019 в 06:51
поделиться

Я собираюсь оптимизировать Ваш regex в целях этого в то, что может работать лучше, но я могу быть неправым, так как я не протестировал его ни на каком реальном коде.

Скажем, Вы сидите в базовом каталоге Вашего кода, Вы могли запустить с:

find . -iname "*.php" -print0

Это получит Вас всех .php файлы, разделенные Нулевыми символами, который необходим в случае, если у любого из них есть пробелы.

find . -iname "*.php" -print0 | xargs -0 -I{} sed -n 's/\(<\?\)\([^a-zA-Z]\)/\1php\2/gp' '{}'

Это должно получить Вас большая часть пути там. Это найдет все файлы, затем для каждого, выполнит sed для замены кода. Однако без тега-i (используемый ниже), это на самом деле не коснется Ваших файлов, он просто отправит Ваш код на Ваш терминал.-n подавляет нормальный вывод и p после того, как regex часть говорит ему печатать только строки, которые изменились.

Хорошо, если Ваши результаты выглядят корректными, то Вы делаете большой шаг, который заменяет оперативные файлы. Необходимо определенно создать резервную копию всех файлов прежде, чем делать попытку этого!!!

find . -iname "*.php" -print0 | xargs -0 -I{} sed -i 's/\(<\?\)\([^a-zA-Z]\)/\1php\2/g' '{}'

Это должно о сделать задание. К сожалению, у меня нет файлов PHP, лежащих вокруг того использования, что синтаксис, таким образом, необходимо самостоятельно изобразить его из здесь, но надо надеяться механика добивания цели, немного более ясен теперь:

  1. Захватите все файлы с "находкой"
  2. Отправьте тот список файлов к "xargs" (который делает некоторую команду на файлах по одному
  3. Используйте "sed" и синтаксис 's/to-change/changed /' для помещения regex волшебства работать!
1
ответ дан 30 November 2019 в 06:51
поделиться

Мой предыдущий ответ, который я просто перезаписал с sed работой привычки, sed, слишком слаб для этого вида вещи IMO.

Таким образом, я сделал на скорую руку perl-сценарий, который должен добиться цели, его, надо надеяться, очень доступный для редактирования пользователем.

#!/usr/bin/perl 

use strict;
use warnings;

use File::Find::Rule;
use Carp;

my @files = File::Find::Rule->file()->name('*.php')->in('/tmp/foo/bar');

for my $file (@files) {
    rename $file, $file . '.orig';
    open my $output, '>', $file or Carp::croak("Write Error with $file $! $@ ");
    open my $input, '<', $file . '.orig'
      or Carp::croak("Read error with $file.orig $! $@");

    while ( my $line = <$input> ) {
        # Replace <?= with <?php echo 
        $line =~ s/<\?=/<?php echo /g;

        # Replace <? ashded  with <?php ashed

        $line =~ s/<\?(?!php|xml)/<?php /g;
        print $output $line;
    }

    close $input  or Carp::carp(" Close error with $file.orig, $! $@");
    close $output or Carp::carp(" Close error with $file  , $! $@");

    unlink $file . '.orig';
}

Но отметьте, я не протестировал это ни на каком реальном коде, таким образом, Он мог пойти "Удар".

Я рекомендовал бы иметь код revisioned (уже ожидайте, revisioned, правильно?..правильно?) и выполненный Ваш набор тестов (Не говорят мне, у Вас нет тестов!) на измененном коде, потому что Вы не можете быть уверены его выполнение правильной вещи без полностью оперенного синтаксического анализатора FSM.

2
ответ дан 30 November 2019 в 06:51
поделиться

Если вы используете параметр токенизатора, это может быть полезно:

$content = file_get_contents($file);
$tokens = token_get_all($content);
$output = '';

foreach($tokens as $token) {
 if(is_array($token)) {
  list($index, $code, $line) = $token;
  switch($index) {
   case T_OPEN_TAG_WITH_ECHO:
    $output .= '<?php echo ';
    break;
   case T_OPEN_TAG:
    $output .= '<?php ';
    break;
   default:
    $output .= $code;
    break;
  }

 }
 else {
  $output .= $token;
 }
}
return $output;

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

14
ответ дан 30 November 2019 в 06:51
поделиться

Это моя версия Regexp:

<\?(?!(php|=|xml))(\s|\t|\n)
1
ответ дан 30 November 2019 в 06:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: