Что нового

Поиск в тексте точного совпадения с шаблоном

A

at

Гость
Код:
$FileSource = FileOpen("Read.txt")
$FileWrite = FileOpen("Write.txt", 2)
$Template = '\bcd\b'

While 1
  $sString = FileReadLine($FileSource)
  If @error = -1 Then ExitLoop
  If StringInStr($sString, $template) Then
    FileWriteLine($FileWrite, $sString)
  EndIf
WEnd

FileClose($FileSource)
FileClose($FileWrite)

Прошу подсказать, как правильно применить регулярное выражение. Из Read.txt нужно скопировать строки в которых содержится точное соответствие "CD". Регистр и знаки пунктуации не важны, но нужно отбрасывать любые строки типа cdrom, cdram, pocds и т.п.
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Если я правильно понял
Код:
$FileSource = FileOpen("Read.txt")
$FileWrite = FileOpen("Write.txt", 2)
$pattern = '(?mi)^.*?\bcd\b.*$'

$sString = FileRead($FileSource)
$aString = StringRegExp($sString, $pattern, 3)
If IsArray($aString) Then
	For $i = 0 To UBound($aString)-1
		FileWriteLine($FileWrite, $aString[$i] & @CRLF)
	Next
EndIf
FileClose($FileSource)
FileClose($FileWrite)

Вроди как-то можно записать сразу массив в файл, но не помню.
Да, и как поступить со строкой "cd cdrom"?
 
Автор
A

at

Гость
Спасибо за помощь. Все работает правильно. Строка "cd cdrom" входит в условия поиска.

По возможности прошу показать решение с использованием StringInStr
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
Если "cd" заведомо находится в середине строки, то просто замените в своём коде "\bcd\b" на " cd ".
Если же "cd" может быть в начале или конце строки, то там надо вводить дополнительные условия.
Хотя может кто-то и сможет это сделать.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
edyapd [?]
Если "cd" заведомо находится в середине строки, то просто замените в своём коде "\bcd\b" на " cd ".
ничего менять не надо. так как '\bcd\b' - паттерн для поиска слова 'cd' вне зависимости от его расположения в строке
Код:
$FileSource = FileOpen("Read.txt")
$FileWrite = FileOpen("Write.txt", 2)
While 1
	$sString = FileReadLine($FileSource)
	If @error = -1 Then ExitLoop
	If StringRegExp($sString, '\bcd\b') Then
		FileWriteLine($FileWrite, $sString)
	EndIf
WEnd
FileClose($FileSource)
FileClose($FileWrite)
 

edyapd

Осваивающий
Сообщения
380
Репутация
30
at сказал(а):
Вот так как раз собирается все подряд.
Будте внимательны, между " и cd (с обоих сторон) стоит ПРОБЕЛ.

joiner, вы тоже не внимательно прочитали. Автор просит:
at сказал(а):
По возможности прошу показать решение с использованием StringInStr
 

alex33

Скриптер
Сообщения
1,457
Репутация
186
at [?]
По возможности прошу показать решение с использованием StringInStr
StringInStr не поддерживает regexp.
Можно так:
Код:
$Template = 'cd'
;...
If StringInStr($sString, $template) > 0 Then
;...


А для проверки соответствия регулярному вырожению можно использовать функцию StringRegExp.
К примеру:
Код:
If StringRegExp($sString, $template) Then
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
со StringInStr не получится лаконично написать. эта функция находит позицию вхождения. а это не значит, что слово "cd" будет отдельным, как хочет автор.оно может быть частью "cdrom", к примеру.
поэтому придется описывать ситуации, когда "cd" с пробелом вначале, когда "cd" с пробелом после, когда "cd"с пробелом до и после, когда "cd" без пробелов и одно в строке, то есть стоит вначале строки.
для тренировки сделать можно все :smile:, но чтобы написать конкретно, то StringInStr тут не подходит
 
Автор
A

at

Гость
Спасибо Все за помощь! Помогли разобраться со StringInStr. Хорошо, если бы это в мануал по регулярным выражениям добавили.


Добавлено:
Сообщение автоматически объединено:

edyapd сказал(а):
alex33 сказал(а):
Можно так:
Код:
$Template = 'cd'
ТС нужно исключить "cdrom, cdram, pocds и т.п."
Так что всё-таки " cd "
В случае, если перед или после CD будут присутствовать знаки пунктуации, то подход с пробелами " CD " отбросит нужные нам строки, а с "CD" мы соберем все подряд. Задача ставилась фильтровать только буквы латинского алфавита от CD, потому в моем случае помогло только экранирование '\bcd\b' с применением StringRegExp. Спасибо еще раз всем за внимание к теме.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
at [?]
прошу показать решение с использованием StringInStr
Код:
This is cd cdrom.
Alice this cdrom, cdrom this Alice.
This cdram, an unknown beast.
What it is pocds?
What it is damcd, it's not a CD?
This CD, it is inserted in the cd rom disk.
CD, it is inserted in the cd rom disk.
This cd

Код:
Local $hFsou = FileOpen("Read.txt")
Local $hFdes = FileOpen("Write.txt", 2)

Local $i = 1
Local $iPos = 0			; позиция вхождения подстроки
Local $aTmp[2]			; массив 'И' (0-0=0; 0-1=0; 1-0=0; 1-1=1)
Local $sPattern = "cd"	; искомое слово
Local $iLength = StringLen($sPattern)

While 1

	$sLine = FileReadLine($hFsou, $i)
	If @error = -1 Then ExitLoop

	$iPos = StringInStr($sLine, $sPattern)

	If $iPos <> 0 Then

		If $iPos = 1 Then
			$aTmp[0] = @CR
		Else
			$aTmp[0] = StringRight(StringMid($sLine, $iPos-1, 1), 1)
		EndIf

		If (StringLen($sLine) - $iPos) = 1 Then
			$aTmp[1] = @LF
		Else
			$aTmp[1] = StringLeft(StringMid($sLine, $iPos + $iLength, 1), 1)
		EndIf

		For $j = 0 To UBound($aTmp) -1
			Switch $aTmp[$j]
				Case '!'
					$aTmp[$j] = 1
				Case '"'
					$aTmp[$j] = 1
				Case '`'
					$aTmp[$j] = 1
				Case ','
					$aTmp[$j] = 1
				Case '-'
					$aTmp[$j] = 1
				Case '.'
					$aTmp[$j] = 1
				Case ':'
					$aTmp[$j] = 1
				Case '?'
					$aTmp[$j] = 1
				Case Chr(32)
					$aTmp[$j] = 1
				Case @LF
					$aTmp[$j] = 1
				Case @CR
					$aTmp[$j] = 1
				Case Else
					$aTmp[$j] = 0
			EndSwitch
		Next

		If $aTmp[0] And $aTmp[1]  Then
			FileWriteLine($hFdes, $sLine)
		EndIf
	EndIf
	$i += 1
WEnd

FileClose($hFsou)
FileClose($hFdes)
 
Верх