Javascript читает "%%" как "%" и "%%"?

При написании теста я сравнивал строки. И тест вернулся, как неудача. Я вручную скопировал вставку строки, и она работает... Обратите внимание на синтаксис строки mysql; но он никогда не касается mysql до этого момента.

Console.logged copy + paste Обе строки выглядят следующим образом:

console.log(replaced);
"SELECT COUNT(*) FROM interaction WHERE ambassador_name LIKE '%' AND influencer_name = ?"

console.log(sqlQuery0);
"SELECT COUNT(*) FROM interaction WHERE ambassador_name LIKE '%' AND influencer_name = ?"

Это не должно терпеть неудачу, но это так. Поэтому я хотел посмотреть, где это не удается:

it( "submits the proper first sql query", function(){
  var replaced = dao.SQLquery[0].replace(/  +/g, ' ');
  for (var i = 0; i < replaced.length; i++) {
    if (replaced[i] != sqlQuery0[i] ){
      console.log(replaced.slice(i-10,i+10));
      console.log(sqlQuery0.slice(i-10,i+10);
      break
    }
  }
})

В МОЙ СУПРУГ ВЫШЕ ВЕРНУТЬСЯ ВЕРНУТЬСЯ...

me LIKE '%' AND inf
me LIKE '%' AND infl

Они не могут быть разной длины.... правильно. Я снова попытался.

  it( "submits the proper first sql query", function(){
    var replaced = dao.SQLquery[0].replace(/  +/g, ' ');
    for (var i = 0; i < replaced.length; i++) {
      if (replaced[i] != sqlQuery0[i] ){
        console.log('|'+ replaced.slice(i-10,i+10)+'|',replaced.slice(i-10,i+10).length);
        console.log('|'+sqlQuery0.slice(i-10,i+10)+'|',sqlQuery0.slice(i-10,i+10).length);
        break
      }
    }
  })

И к моему большому удивлению:

|me LIKE '%' AND inf| 20
|me LIKE '%' AND infl| 20

Но первая строка имеет длину 19!

Мой последний аттапт:

var replaced = dao.SQLquery[0].replace(/  +/g, ' ');
for (var i = 0; i < replaced.length; i++) {
  console.log(replaced[i], sqlQuery0[i]);
  if (replaced[i] != sqlQuery0[i] ){
    console.log('|'+ replaced.slice(i-10,i+10)+'|',replaced.slice(i-10,i+10).length);
    console.log('|'+sqlQuery0.slice(i-10,i+10)+'|',sqlQuery0.slice(i-10,i+10).length);
    break
  }
}

дал мне это:

n n
a a
m m
e e

L L
I I
K K
E E

' '
% %
% '
|me LIKE '%' AND inf| 20
|me LIKE '%' AND infl| 20

По-видимому, "%%" интерпретируется как% и %%, как это может быть?

больше:

var replaced = dao.SQLquery[0].replace(/  +/g, ' ');
console.log(sqlQuery0)
for (var i = 0; i < replaced.length; i++) {
  console.log(replaced[i], sqlQuery0[i]);
  if (replaced[i] != sqlQuery0[i] ){
    console.log('|'+ JSON.stringify(replaced.slice(i-10,i+10))+'|',replaced.slice(i-10,i+10).length);
    console.log('|'+ JSON.stringify(sqlQuery0.slice(i-10,i+10))+'|',sqlQuery0.slice(i-10,i+10).length);
    console.log('|'+ JSON.stringify(dao.SQLquery[0].slice(i-10,i+10))+'|',sqlQuery0.slice(i-10,i+10).length);
    break
  }
}

|"me LIKE '%' AND inf"| 20
|"me LIKE '%' AND infl"| 20
|"ame LIKE '%' AND in"| 20

Ответы

Ответ 1

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

Например:

var a = 'foo\u200bbar';
var b = 'foobar';

console.log('a = "' + a + '"');
console.log('b = "' + b + '"');

function toCodePointArray(str) {
    var result = [];
    for (var i = 0; i < str.length; i++) {
        result.push(str.charCodeAt(i));
    }
    return result;
}

console.log('toCodePointArray(a) = ', toCodePointArray(a));
console.log('toCodePointArray(b) = ', toCodePointArray(b)); 

Когда я запускаю это, я получаю:

a = "foo​bar"
b = "foobar"
toCodePointArray(a) =  [ 102, 111, 111, 8203, 98, 97, 114 ]
toCodePointArray(b) =  [ 102, 111, 111, 98, 97, 114 ]

Здесь скрытый символ четко отображается как 8203, который является десятичным эквивалентом 0x200b, который является пространством нулевой ширины Unicode.

Ответ 2

расширяя то, что сказал @Matt Ball и @blm, у вас, скорее всего, есть "невидимый" символ в тексте, который находится в вашей "замененной" переменной. Чтобы проверить это, используйте шестнадцатеричный редактор и вставьте текст из переменных "replace" и sqlQuery0: вы должны видеть, что вокруг символа "%" у вас есть невидимый символ типа "00" NUL или "1E", разделитель записей.

Вы можете использовать этот онлайн-инструмент Hex Viewer для тестирования https://hexed.it/?hl=en

чтобы увидеть коды ASCII, на которые я ссылаюсь, проверьте таблицу ascii http://www.asciitable.com/

Ответ 3

чтобы избежать этой проблемы, которая создает дополнительные биты, используйте hex char val. для% it 0x25

"SELECT COUNT(*) FROM interaction WHERE ambassador_name LIKE "X'250225'" AND influencer_name = ?"

или даже

    "SELECT COUNT(*) FROM interaction WHERE ambassador_name LIKE "%X'250225'%" AND influencer_name = ?"

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

"SELECT COUNT(*) FROM interaction WHERE LOCATE(X'25', ambassador_name) > 0  AND influencer_name = ?"

также, как говорит Роб Уилсон, чтобы избежать лишних беспорядочных битов в юникодах при использовании LIKE, всегда связывайте PDO:: PARAM_STR для LIKE. В процессе ускорения инъекции PDO также очищает эти дополнительные биты.

SELECT COUNT(*) FROM interaction WHERE ambassador_name LIKE ? AND influencer_name = ?

bindParam(1, "X'250225'", PDO::PARAM_STR);

или даже

    bindParam(1, "%X'250225'%", PDO::PARAM_STR);