Что нового

[Данные, строки] Поиск нескольких подстрок в строке с помощью регулярных выражений

glax24

Знающий
Сообщения
72
Репутация
14
Начал разбираться с регулярными выражениями но ничего не получилось.
Помогите разобраться.
В массиве строк $aString надо найти все строки которые удовлетворяют условиям.
1. Регулярное выражение для поиска всех х86
2. Регулярное выражение для поиска всех х64
3. Почему если строка и подстрока на русском не работает независимость от регистра (?i)
Код:
#include <String.au3>
#include <Array.au3>
Global $i
Global $sRegExp86
Global $sRegExp64

;Поиск в строке нескольких подстрок

Global $sSubStr1 = "Windows" ;1 - Подстрока всегда есть
Global $sSubStr2 = "Professional" ;2- Может быть и = ""
;Подстроки 3-4 - независимо от положения в строке, тк может их и не быть или располагаться произвольно в строке
Global $sSubStr3 = "(?:x64|64-bit)" ; Исключить из поиска x64 или 64-bit, для поиска x86
Global $sSubStr4 = "(x64|64-bit)"

; примеры строк
Global $aString[7] = ["Windows 1 Professional", _ ;x86
		"Windows 2 Professional (x86)", _ ;x86
		"Windows 3 (x86) Professional", _ ;x86
		"Windows 4 Professional (x64)", _ ;x64
		"Windows 5 Professional x64", _ ;x64
		"Windows 6 (x64) Professional", _ ;x64
		"Windows 7 Professional (64-bit)"] ; x64
;Вопрос 1
;Регулярное выражение с привязкой к положению подстрок
$sRegExp86 = '(?i)(' & $sSubStr1 & '.*' & $sSubStr2 & ')' & '.*' & $sSubStr3 ; не правильно задан $sSubStr3
$sRegExp64 = '(?i)(' & $sSubStr1 & '.*' & $sSubStr2 & ')' & '.*' & $sSubStr4

;Вопрос 2
;Регулярное выражение без привязки к положению подстрок $sSubStr3 и $sSubStr4
; Незнаю как
;$sRegExp86 = ?????
;$sRegExp64 = ?????

;Вопрос 3
; Если строка и подстрока на русском не работает независимость от регистра (?i)
MsgBox(0, "", 'Результат поиска в строке "Как дела" подстроки "(?i)как" =' & StringRegExp("Как дела", "(?i)как"))


; Показать все результаты подходящие для x86
For $i = 0 To UBound($aString) - 1
	TestRegExp($aString[$i], $sRegExp86, "x86")
Next

; Показать все результаты подходящие для x64
For $i = 0 To UBound($aString) - 1
	TestRegExp($aString[$i], $sRegExp64, "x64")
Next

; Вернуть 1 если все подстроки найдены или удовлетворяют условию
Func TestRegExp($sString, $sSubStrRegExp, $sTitle = "")
	Local $flag = 0
	Local $Res
	ConsoleWrite($sSubStrRegExp & @CRLF)
	$Res = StringRegExp($sString, $sSubStrRegExp, $flag)

	;If $flag Then _ArrayDisplay($Res,$sTitle)
	If Not $flag Then
		;Если в строке найдены все подстроки то показать сообщение
		If $Res Then MsgBox(0, $sTitle, $sSubStrRegExp & @CRLF & $sString)
	EndIf
EndFunc   ;==>TestRegExp
 

joiner

Модератор
Локальный модератор
Сообщения
3,461
Репутация
609
ну в данном конкретном примере я бы решил так
Код:
#include <String.au3>
#include <Array.au3>
; примеры строк
Global $aString[7] = ["Windows 1 Professional", _ ;x86
        "Windows 2 Professional (x86)", _ ;x86
        "Windows 3 (x86) Professional", _ ;x86
        "Windows 4 Professional (x64)", _ ;x64
        "Windows 5 Professional x64", _ ;x64
        "Windows 6 (x64) Professional", _ ;x64
        "Windows 7 Professional (64-bit)"] ; x64

; Показать все результаты подходящие для x64
_ArrayDisplay($aString)
Dim $new_string[1]
For $i = 0 To UBound($aString) - 1
	If StringInStr($aString[$i],'64' ) <> 0 Then _ArrayAdd($new_string,$aString[$i])
Next

_ArrayDisplay($new_string)
;если StringInStr($aString[$i],'64' ) = 0 то получим массив названия 32-битных систем
 
Автор
G

glax24

Знающий
Сообщения
72
Репутация
14
Такое решение не пойдет надо более точное определение. Например если будет строка
Код:
Windows 64 Professional
данна строка относится к x86, а у вас будет к x64.
Также нет проверки ключевых слов например как Windows-первая подстрока должна быть всегда, смотрите в моем примере комментарии.
 

Redline

AutoIT Гуру
Сообщения
506
Репутация
370
Код:
#include <String.au3>
в данном случае вообще не нужен
Код:
Global $sSubStr3 = "(?:x64|64-bit)" ; Исключить из поиска x64 или 64-bit, для поиска x86

Этот шаблон работает не так как вам надо: он ищет x64 или 64-bit, но не захватывает их.
Я заменил это на негативный просмотр вперед, т.е. такую строку, в которой после Windows.. не идет x64 или 64-bit.
Код:
Global $sSubStr2 = "Professional" ;2- Может быть и = ""

Если этот сочетание может быть или нет, то нужно запаковать его в скобки и поставить квантификатор "?"
А можно было вообще его выкинуть из шаблона, т.к. оно не несет никакой смысловой или определяющей нагрузки.
1. + 2.:
Код:
#include <Array.au3>
Global $i
Global $sRegExp86
Global $sRegExp64

;Поиск в строке нескольких подстрок

Global $sSubStr1 = "Windows" ;1 - Подстрока всегда есть
Global $sSubStr2 = "(Professional)?" ;2- Может быть и = ""
;Подстроки 3-4 - независимо от положения в строке, тк может их и не быть или располагаться произвольно в строке
Global $sSubStr3 = "(?!.*?x64|.*?64-bit)" ; Исключить из поиска x64 или 64-bit, для поиска x86
Global $sSubStr4 = "(x64|64-bit)"

; примеры строк
Global $aString[7] = ["Windows 1 Professional", _ ;x86
        "Windows 2 Professional (x86)", _ ;x86
        "Windows 3 (x86) Professional", _ ;x86
        "Windows 4 Professional (x64)", _ ;x64
        "Windows 5 Professional x64", _ ;x64
        "Windows 6 (x64) Professional", _ ;x64
        "Windows 7 Professional (64-bit)"] ; x64
;Вопрос 1
;Регулярное выражение с привязкой к положению подстрок
$sRegExp86 = '(?i)' & $sSubStr3 & $sSubStr1 & '.*?' & $sSubStr2
$sRegExp64 = '(?i)' & $sSubStr1 & '.*?' & $sSubStr2 & $sSubStr4 & $sSubStr2

;Вопрос 2
;Регулярное выражение без привязки к положению подстрок $sSubStr3 и $sSubStr4
; Незнаю как
;$sRegExp86 = ?????
;$sRegExp64 = ?????

;Вопрос 3
; Если строка и подстрока на русском не работает независимость от регистра (?i)
;~ MsgBox(0, "", 'Результат поиска в строке "Как дела" подстроки "(?i)как" =' & StringRegExp("Как дела", "(?i)как"))


; Показать все результаты подходящие для x86
For $i = 0 To UBound($aString) - 1
    TestRegExp($aString[$i], $sRegExp86, "x86")
Next

; Показать все результаты подходящие для x64
For $i = 0 To UBound($aString) - 1
    TestRegExp($aString[$i], $sRegExp64, "x64")
Next

; Вернуть 1 если все подстроки найдены или удовлетворяют условию
Func TestRegExp($sString, $sSubStrRegExp, $sTitle = "")
    Local $flag = 0
    Local $Res
    ConsoleWrite($sSubStrRegExp & @CRLF)
    $Res = StringRegExp($sString, $sSubStrRegExp, $flag)

    ;If $flag Then _ArrayDisplay($Res,$sTitle)
    If Not $flag Then
        ;Если в строке найдены все подстроки то показать сообщение
        If $Res Then MsgBox(0, $sTitle, $sSubStrRegExp & @CRLF & $sString)
    EndIf
EndFunc   ;==>TestRegExp
Гибкий шаблон настроить можно, для этого нужно перечислить все возможные комбинации, которые могут встретиться в строке и это довольно трудоемко для данного количества комбинаций.
3. Наверно это было сложно реализовать.


Кстати этот пример проще реализовать через StringInStr:

Код:
Global $aString[7] = ["Windows 1 Professional", _ ;x86
        "Windows 2 Professional (x86)", _ ;x86
        "Windows 3 (x86) Professional", _ ;x86
        "Windows 4 Professional (x64)", _ ;x64
        "Windows 5 Professional x64", _ ;x64
        "Windows 6 (x64) Professional", _ ;x64
        "Windows 7 Professional (64-bit)"] ; x64

For $i = 0 To UBound($aString) - 1
	ConsoleWrite($aString[$i] & @CRLF)
    If StringInStr($aString[$i],'x64' ) Or StringInStr($aString[$i],'64-bit' ) Then
		ConsoleWrite('x64' & @CRLF)
	Else
		ConsoleWrite('x86' & @CRLF)
	EndIf
Next
 

joiner

Модератор
Локальный модератор
Сообщения
3,461
Репутация
609
Redline
пример с использованием
Код:
StringInStr

и я привел, но как я понял, нужно чтобы было еще обязательно слово Windows
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Вариант :
Код:
#include <Array.au3>

Global $aString[7] = ["Windows 1 Professional", _ ;x86
        "Windows 2 Professional (x86)", _ ;x86
        "Windows 3 (x86) Professional", _ ;x86
        "Windows 4 Professional (x64)", _ ;x64
        "Windows 5 Professional x64", _ ;x64
        "Windows 6 (x64) Professional", _ ;x64
        "Windows 7 Professional (64-bit)"] ; x64

_ArrayDisplay($aString, "$aString")

$sText=_ArrayToString($aString, @CRLF)
ConsoleWrite ("$sText= " &$sText & @LF)

$a_x64=StringRegExp( $sText, '(?i)(.*(?:x64|64-bit).*)', 3 )
$a_x86=StringRegExp( $sText, '(?mi)^(.*x86.*|[^x-]*?)$', 3 )
_ArrayDisplay($a_x64, "$a_x64")

_ArrayDisplay($a_x86, "$a_x86")
 

joiner

Модератор
Локальный модератор
Сообщения
3,461
Репутация
609
joiner [?]
и я привел, но как я понял, нужно чтобы было еще обязательно слово Windows
Код:
$a_x64=StringRegExp( $sText, '(?i)windows.*(?:x64|64-bit).*', 3 )

будут найдены только строчки где есть слово Windows и x64|64-bit
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
В принципе я показывал вариант использования _ArrayToString.
А там можно учесть все ограничения:
И обязательность Windows
и возможное наличие пробелов перед ним и т.д.

Код:
$sText=_ArrayToString($aString, @CRLF)
$a_x64=StringRegExp( $sText, '(?i)(\s*windows.*(?:x64|64-bit).*)', 3 )
$a_x86=StringRegExp( $sText, '(?mi)^(\s*windows.*x86.*|[^x-]*?)$', 3 )
 

Redline

AutoIT Гуру
Сообщения
506
Репутация
370
joiner [?]
Redlineпример с использованием Код: AutoIt [Выделить]StringInStr и я привел, но как я понял, нужно чтобы было еще обязательно слово Windows
Ну тогда так: ;)
Код:
Global $aString[7] = ["Windows 1 Professional", _ ;x86
        "Windows 2 Professional (x86)", _ ;x86
        "Windows 3 (x86) Professional", _ ;x86
        "Windows 4 Professional (x64)", _ ;x64
        "Windows 5 Professional x64", _ ;x64
        "Windows 6 (x64) Professional", _ ;x64
        "Windows 7 Professional (64-bit)"] ; x64

For $i = 0 To UBound($aString) - 1
	ConsoleWrite($aString[$i] & @CRLF)
	If StringLower(StringLeft($aString[$i], 7)) = 'windows' Then
		If StringInStr($aString[$i],'x64') Or StringInStr($aString[$i],'64-bit') Then
			ConsoleWrite('x64' & @CRLF)
		Else
			ConsoleWrite('x86' & @CRLF)
		EndIf
	EndIf
Next
 
Верх