PHP: Как удалить все непечатаемые символы в строке?

Когда вы используете веб-холсты WebGL, браузеры (включая настольные) будут налагать дополнительные ограничения на размер базового буфера. Даже если ваш холст большой, например. 16,000x16,000, большинство браузеров отобразит изображение меньшего размера (скажем, 4096x4096) и увеличит его. Это может вызвать уродливое пикселирование и т. Д.

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

function makeGLCanvas()
{
    // Get A WebGL context
    var canvas = document.createElement('canvas');
    var contextNames = ["webgl", "experimental-webgl"];
    var gl = null;
    for (var i = 0; i < contextNames.length; ++i)
    {
        try
        {
            gl = canvas.getContext(contextNames[i], {
                // Used so that the buffer contains valid information, and bytes can
                // be retrieved from it. Otherwise, WebGL will switch to the back buffer
                preserveDrawingBuffer: true
            });
        }
        catch(e) {}
        if (gl != null)
        {
            break;
        }
    }
    if (gl == null)
    {
        alert("WebGL not supported.\nGlobus won't work\nTry using browsers such as Mozilla " +
            "Firefox, Google Chrome or Opera");
        // TODO: Expecting that the canvas will be collected. If that is not the case, it will
        // need to be destroyed somehow.
        return;
    }

    return [canvas, gl];
}

// From Wikipedia
function gcd(a,b) {
    a = Math.abs(a);
    b = Math.abs(b);
    if (b > a) {var temp = a; a = b; b = temp;}
    while (true) {
        if (b == 0) return a;
        a %= b;
        if (a == 0) return b;
        b %= a;
    }
}

function isGlContextFillingTheCanvas(gl) {
    return gl.canvas.width == gl.drawingBufferWidth && gl.canvas.height == gl.drawingBufferHeight;
}

// (See issue #2) All browsers reduce the size of the WebGL draw buffer for large canvases 
// (usually over 4096px in width or height). This function uses a varian of binary search to
// find the maximum size for a canvas given the provided x to y size ratio.
//
// To produce exact results, this function expects an integer ratio. The ratio will be equal to:
// xRatio/yRatio.
function determineMaxCanvasSize(xRatio, yRatio) {
    // This function works experimentally, by creating an actual canvas and finding the maximum
    // value, the browser allows.
    [canvas, gl] = makeGLCanvas();

    // Reduce the ratio to minimum
    gcdOfRatios = gcd(xRatio, yRatio);
    [xRatio, yRatio] = [xRatio/gcdOfRatios, yRatio/gcdOfRatios];

    // if the browser cannot handle the minimum ratio, there is not much we can do
    canvas.width = xRatio;
    canvas.height = yRatio;

    if (!isGlContextFillingTheCanvas(gl)) {
        throw "The browser is unable to use WebGL canvases with the specified ratio: " + 
            xRatio + ":" + yRatio;
    }

    // First find an upper bound
    var ratioMultiple = 1;  // to maintain the exact ratio, we will keep the multiplyer that
                            // resulted in the upper bound for the canvas size
    while (isGlContextFillingTheCanvas(gl)) {
        canvas.width *= 2;
        canvas.height *= 2;
        ratioMultiple *= 2;
    }

    // Search with minVal inclusive, maxVal exclusive
    function binarySearch(minVal, maxVal) {
        if (minVal == maxVal) {
            return minVal;
        }

        middle = Math.floor((maxVal - minVal)/2) + minVal;

        canvas.width = middle * xRatio;
        canvas.height = middle * yRatio;

        if (isGlContextFillingTheCanvas(gl)) {
            return binarySearch(middle + 1, maxVal);
        } else {
            return binarySearch(minVal, middle);
        }
    }

    ratioMultiple = binarySearch(1, ratioMultiple);
    return [xRatio * ratioMultiple, yRatio * ratioMultiple];
}

Также в jsfiddle https://jsfiddle.net/1sh47wfk/1/

141
задан Stewart Robinson 24 July 2009 в 10:48
поделиться

3 ответа

7-битный ASCII?

Если ваш Тардис только что приземлился в 1963 году, а вам просто нужен 7-битные печатаемые символы ASCII, вы можете вырвать все от 0-31 и 127-255 с помощью этого:

$string = preg_replace('/[\x00-\x1F\x7F-\xFF]/', '', $string);

Он соответствует чему-либо в диапазоне 0-31, 127-255 и удаляет его.

8-битный расширенный ASCII?

Вы попали в машину времени в джакузи, и вы вернулись в восьмидесятые. Если у вас есть какая-то форма 8-битного ASCII, вы можете оставить символы в диапазоне 128-255. Легкая настройка - просто найдите 0-31 и 127

$string = preg_replace('/[\x00-\x1F\x7F]/', '', $string);

UTF-8?

А, добро пожаловать в 21 век. Если у вас есть строка в кодировке UTF-8, то модификатор / u можно использовать в регулярном выражении

$string = preg_replace('/[\x00-\x1F\x7F]/u', '', $string);

. Это просто удаляет 0-31 и 127. Это работает в ASCII и UTF-8. потому что оба используют один и тот же диапазон контрольного набора (как указано ниже в mgutt). Строго говоря, это работало бы без модификатора / u . Но это упрощает жизнь, если вы хотите удалить другие символы ...

Если вы имеете дело с Unicode, существует потенциально много непечатаемых элементов , но давайте рассмотрим простой: NO-BREAK SPACE (U + 00A0)

В строке UTF-8 это будет закодировано как 0xC2A0 . Вы можете найти и удалить эту конкретную последовательность, но с установленным модификатором / u вы можете просто добавить \ xA0 к классу символов:

$string = preg_replace('/[\x00-\x1F\x7F\xA0]/u', '', $string);

Приложение: А как насчет str_replace ?

preg_replace довольно эффективен, но если вы выполняете эту операцию много раз, вы можете создать массив символов, которые хотите удалить, и использовать str_replace, как указано в mgutt ниже, например

//build an array we can re-use across several operations
$badchar=array(
    // control characters
    chr(0), chr(1), chr(2), chr(3), chr(4), chr(5), chr(6), chr(7), chr(8), chr(9), chr(10),
    chr(11), chr(12), chr(13), chr(14), chr(15), chr(16), chr(17), chr(18), chr(19), chr(20),
    chr(21), chr(22), chr(23), chr(24), chr(25), chr(26), chr(27), chr(28), chr(29), chr(30),
    chr(31),
    // non-printing characters
    chr(127)
);

//replace the unwanted chars
$str2 = str_replace($badchar, '', $str);

Интуитивно это кажется это было бы быстро, но это не всегда так, вам обязательно стоит провести тест, чтобы увидеть, спасет ли это вас что-нибудь. Я провел несколько тестов для различных длин строк со случайными данными, и этот шаблон появился с использованием php 7.0.12

     2 chars str_replace     5.3439ms preg_replace     2.9919ms preg_replace is 44.01% faster
     4 chars str_replace     6.0701ms preg_replace     1.4119ms preg_replace is 76.74% faster
     8 chars str_replace     5.8119ms preg_replace     2.0721ms preg_replace is 64.35% faster
    16 chars str_replace     6.0401ms preg_replace     2.1980ms preg_replace is 63.61% faster
    32 chars str_replace     6.0320ms preg_replace     2.6770ms preg_replace is 55.62% faster
    64 chars str_replace     7.4198ms preg_replace     4.4160ms preg_replace is 40.48% faster
   128 chars str_replace    12.7239ms preg_replace     7.5412ms preg_replace is 40.73% faster
   256 chars str_replace    19.8820ms preg_replace    17.1330ms preg_replace is 13.83% faster
   512 chars str_replace    34.3399ms preg_replace    34.0221ms preg_replace is  0.93% faster
  1024 chars str_replace    57.1141ms preg_replace    67.0300ms str_replace  is 14.79% faster
  2048 chars str_replace    94.7111ms preg_replace   123.3189ms str_replace  is 23.20% faster
  4096 chars str_replace   227.7029ms preg_replace   258.3771ms str_replace  is 11.87% faster
  8192 chars str_replace   506.3410ms preg_replace   555.6269ms str_replace  is  8.87% faster
 16384 chars str_replace  1116.8811ms preg_replace  1098.0589ms preg_replace is  1.69% faster
 32768 chars str_replace  2299.3128ms preg_replace  2222.8632ms preg_replace is  3.32% faster

. Сами тайминги рассчитаны на 10000 итераций, но что более интересно, так это относительные различия. До 512 символов я всегда видел, как preg_replace выигрывает. В диапазоне 1-8 КБ str_replace имеет крайний край.

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

324
ответ дан 23 November 2019 в 22:38
поделиться

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

$string=preg_replace('/[^A-Za-z0-9 _\-\+\&]/','',$string);

Заменяет все, что не (^), буквы AZ или AZ, цифры 0-9 , пробел, подчеркивание, выделение, плюс и амперсанд - без ничего (т.е. удалить его).

6
ответ дан 23 November 2019 в 22:38
поделиться

вы можете использовать классы символов

/[[:cntrl:]]+/
26
ответ дан 23 November 2019 в 22:38
поделиться
Другие вопросы по тегам:

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