preg_match исключить строки - PullRequest
0 голосов
/ 26 февраля 2011

Из 10000 строк данных мне нужно получить все строки, которые не содержат слова, которые начинаются как "en" или "it" или "de" и т. Д., То есть от 2 до5 длинных az и AZ с «-» тоже (знак минус) и «;»

Я пробовал это, но не работает

 !preg_match("/\b(it|en|de|es|fr|ru)[a-zA-Z-;]{2,5}/", $value)

это будет прочитано (для меня) donне совпадают, все строки имеют слова, начинающиеся с него, en и т. д. состоят из 2–5 символов и в этих 5 символах могут также содержаться символы «-» или «;».

Это возвращает мне строкис этим;"который я должен исключить.

РЕДАКТИРОВАТЬ: мне нужно сопоставить каждое слово, которое начинается с этих 2 символов ( it или en или de ) и может быть везде в строке

Пример для сопоставления (он не содержит слов, начинающихся с "en", "de" и т. д.)

GET; SITE; 15:03:03; ; Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1; .NET4.0C); 

Пример не дляmatch (оно содержит слово, начинающееся с «en»)

GET; SITE; 13:06:49; ; Mozilla/4.0 (compatible; **en;** MSIE 8.0; Windows NT 6.1; Trident/4.0; SIMBAR={E76F6580-EB92-49A3-A089-F6B8B9DEA9AA}; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; eSobiSubscriber 2.0.4.16; Media Center PC 5.0; SLCC1; .NET4.0C); ; 

Ответы [ 4 ]

4 голосов
/ 26 февраля 2011

Насколько я могу судить, ваше регулярное выражение соответствует строкам, которые начинаются с одного из кодов стран и имеют общую длину 4 - 7 , а не 2 - 5. Так что en; не совпадает потому что он содержит только три символа. {2,5} применяется только к выражению слева от него, поэтому ваше регулярное выражение гласит: «Слово, которое начинается с него / en / de и т. Д. И продолжается от двух до пяти букв / тире / точек с запятой». Попробуйте \b(it|en|de|es|fr|ru)[a-zA-Z-;]{0,3}.

Возможно, вы также захотите уточнить, что точка с запятой является последним символом, а также, возможно, более конкретно о структуре кодов языка ISO (что я предполагаю, что эти строки): \b(it|en|de|es|fr|ru)(-[a-zA-Z]{2})?;?\b. Здесь мы говорим: «Слово, которое начинается с него / en / de и т. Д. И может продолжаться с тире и двумя буквами, и (независимо от того, было ли у него тире и две буквы) может продолжаться точкой с запятой. Ничего другого не будет разрешено до окончания слова. "

1 голос
/ 26 февраля 2011

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

$lines = explode("\n", $data); // I'm making an assumption here, discussed below.
foreach ($lines as $line)
{
  if (!preg_match('/\b(?=it|en|de|es|fr|ru)[a-z;-]{2,5}/i', $line))
  {
    // line doesn't contain a word beginning with en, de, etc.
  }
}

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

Я использую положительное прогнозное утверждение ((?=)), чтобы проверить, являются ли первые два символа слова искомыми языковыми кодами. Это позволяет избежать проблемы, которую @Aasmund Eldhuset указал в своем ответе . Другими словами, механизм регулярных выражений ищет слова, начинающиеся с кодов языка, которые вы хотите исключить, но затем результат сопоставления логически инвертируется PHP, поэтому любые строки, содержащие эти слова, игнорируются.


Я предполагаю, что ваши данные разбиты на строки одним \n (символом новой строки). Вместо этого он может быть разделен на \r или \n\r. Если вы не знаете, какие символы новой строки используются, вы можете использовать preg_split вместо explode, то есть:

$lines = preg_split('/\n|\n?\r/', $data);
0 голосов
/ 26 февраля 2011

Вы можете использовать упреждающее утверждение :

/\b(?!it|en|de|es|fr|ru)[a-zA-Z-;]{2,5}/

Здесь (?!…) утверждает, что не должно быть совпадения содержащего паттерна с текущей позиции безсоответствующий этому шаблону.

0 голосов
/ 26 февраля 2011

Магический персонаж, которого вы ищете, это каретка: ^:

!preg_match("/^(it|en|de|es|fr|ru)[a-zA-Z-;]{2,5}/", $value)

Кроме того, выглядит хорошо.

...