Что нового

Извлечение полного имени папки RegExp'ом, из нестандартного пути

sforce5

Олл фо ЛулзЪ
Сообщения
160
Репутация
41
К примеру есть пути:

Код:
C:\Program Files\Unknown\setup.exe /QWERTY
C:\Program Files\Nudoi\unipath.exe GUI
"C:\Program Files\SV Vision\jrarth.exe" /jellyroger /hide
нужно из такого вида путей извлечь нормальные, полноценные пути: к файлу, к папке.

у меня никак не получается
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
а без ключей пути есть?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Я думаю вряд ли это можно решить только регулярными выражениями (хотя могу и ошибаться), особенно для первых двух случаев. Ведь файл может и не содержать расширения или параметром может служить другое имя файла... Для подобных целей я написал следующую функцию, но только здесь файл должен присутствовать по указанному пути, подозреваю, тебе это и нужно.

Код:
ConsoleWrite(_ExtractPath('C:\Program Files\Unknown\setup.exe /QWERTY') & @CR)
ConsoleWrite(_ExtractPath('C:\Program Files\Nudoi\unipath.exe GUI') & @CR)
ConsoleWrite(_ExtractPath('"C:\Program Files\SV Vision\jrarth.exe" /jellyroger /hide') & @CR)

Func _ExtractPath($sPath)
	$sPath = StringStripWS($sPath, 7)
	If StringLeft($sPath, 1) = '"' Then
		$sPath = StringRegExpReplace($sPath, '\A"+|".*\z', '')
		If Not FileExists($sPath) Then
			$sPath = ''
		EndIf
	Else
		While Not FileExists($sPath)
			$sPath = StringLeft($sPath, StringInStr($sPath, ' ', 0, -1) - 1)
			If $sPath = '' Then
				ExitLoop
			EndIf
		WEnd
	EndIf
	Return $sPath
EndFunc   ;==>_ExtractPath
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Код:
$a = 'C:\Program Files\Unknown\setup.exe /QWERTY'
$b = 'C:\Program Files\Nudoi\unipath.exe GUI'
$c = '"C:\Program Files\SV Vision\jrarth.exe" /jellyroger /hide'
$d = '"C:\test.exe" /key1 /key2"'
$e = '"C:\Program Files\SV Vision\jrarth.exe"'
$pattern = '"?(\D\:(\\.+)+\w+\.\w+)"?.*'
MsgBox(0, '', StringRegExpReplace($a, $pattern, '\1'))
MsgBox(0, '', StringRegExpReplace($b, $pattern, '\1'))
MsgBox(0, '', StringRegExpReplace($c, $pattern, '\1'))
MsgBox(0, '', StringRegExpReplace($d, $pattern, '\1'))
MsgBox(0, '', StringRegExpReplace($e, $pattern, '\1'))
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Kaster, как я уже написал, а что если

C:\Program Files\Nudoi\unipath.exe test.exe
 

Suppir

Продвинутый
Сообщения
967
Репутация
62
Re: Извлечение полного имени папки RegExp\\\'ом, из нестандартного пути

Вот регулярное выражение, которое ловит все случаи:
кроме случая, когда у файла нет расширения (тогда нужно писать пакет регулярных выражений для доскональной проверки)

""*(.+?\.\w+)


Проверочный код:

Код:
$a = "C:\Program Files\Unknown\setup.exe /QWERTY"
$b = "C:\Program Files\Nudoi\unipath.exe GUI"
$c = """C:\Program Files\SV Vision\jrarth.exe"" /jellyroger /hide"

$aMatches = StringRegExp($a, """*(.+?\.\w+)", 1)
if @error = 0 Then MsgBox(0, "", $aMatches[0])
	
$aMatches = StringRegExp($b, """*(.+?\.\w+)", 1)
if @error = 0 Then MsgBox(0, "", $aMatches[0])

$aMatches = StringRegExp($c, """*(.+?\.\w+)", 1)
if @error = 0 Then MsgBox(0, "", $aMatches[0])


:whistle:


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

Вариант "C:\Program Files\Nudoi\unipath.exe test.exe", предложенный Yashied'ом, также ловит.


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

А вот регулярка для отлова папок:

""*(.+)\\
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Suppir, супер, только одно замечание, что если

C:\Program Files\UNKNOWN.DAT\setup.exe /QWERTY

Можешь поправить?
 

Suppir

Продвинутый
Сообщения
967
Репутация
62
Re: Извлечение полного имени папки RegExp\'ом, из нестандартного пути

Это дополнительное условие. Нужно подумать :smile:


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

В таком случае предлагаю решать проблему в два прохода:

Код:
$a = "C:\Program Files\UNKNOWN.DAT\setup.exe /QWERTY"

;~ сначала удаляем ключи (если есть)
$a = StringRegExpReplace($a, " /.+", "")

;~ затем ищем имя файла
$aMatches = StringRegExp($a, """*(.+\.\w+)", 1)

;~ результат
if @error = 0 Then MsgBox(0, "", $aMatches[0])
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Супер №2.

+1
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 159
Репутация
2 329
Re: Извлечение полного имени папки RegExp\'ом, из нестандартного пути

http://autoit-script.ru/index.php?topic=316.0


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

Suppir [?]
В таком случае предлагаю решать проблему в два прохода
Не обязательно, в таком случае можно указать на конец строки:

Код:
$1 = 'C:\Program Files\Unknown.dat\setup.exe /QWERTY'
$2 = '"C:\Program Files\SV Vision\jrarth.exe" GUI'
$3 = '"C:\Program Files\SV Vision\jrarth.exe" /jellyroger /hide'
$4 = '"C:\test.exe" /key1 /key2"'
$5 = 'C:\Program Files\Unknown.dat\setup.exe test.exe'

For $i = 1 To 5
	;~ удаляем ключи (если есть)
	$Var = StringRegExpReplace(Eval($i), '(?i) (/.+|[а-яА-Я\w\d\._-]+)$|"', '')
	
	;~ результат
	MsgBox(0, $i, $Var)
Next
 

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
CreatoR
Кавычки не удаляются.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
CreatoR,

C:\Program Files\Unknown.dat\setup.exe test.exe

Не работает.

:(
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 159
Репутация
2 329
Re: Извлечение полного имени папки RegExp\'ом, из нестандартного пути

Yashied [?]
Поправил, теперь в параметре также поддерживается дефис, символ подчёркивания, цифры, точки, и русские символы.


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

madmasles [?]
Кавычки не удаляются
А должны?

Тоже подправил.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Вот небольшой сравнительный тест, это обычные строки, которые могут содержаться в реестре и как правило возвращаются функцией _WinAPI_AssocQueryString(). Пока мой способ впереди планеты всей (ну не люблю я регулярные выражения), но, как я уже сказал ранее, файл должен существовать на диске. Это конечно большой минус, но как правило пути извлекают для существующих файлов.

Код:
Dim $aPath[8]

$aPath[0] = '"C:\Program Files\Unknown.dat\setup.exe" test.exe'
$aPath[1] = 'C:\Program Files\Unknown.dat\setup.exe test.exe'
$aPath[2] = 'C:\Program Files\Unknown.dat\setup.exe /d test.exe'
$aPath[3] = 'C:\Program Files\Unknown.dat\setup.exe test.exe /d'
$aPath[4] = 'C:\Program Files\Unknown.dat\setup.exe C:\#test.exe'
$aPath[5] = 'C:\Program Files\Unknown.dat\setup.exe #d C:\test.exe'
$aPath[6] = 'C:\Program Files\Unknown.dat\setup.exe test1.exe test2.exe'
$aPath[7] = 'C:\Program Files\Unknown.dat\setup.exe %1 -d -text.log'

For $i = 0 To UBound($aPath) - 1
    ; CreatoR
    ConsoleWrite('CreatoR: ' & StringRegExpReplace($aPath[$i], '(?i) (/.+|[а-яА-Я\w\d\._-]+)$|"', '') & @CR)

    ; Suppir
    $aMatches = StringRegExp(StringRegExpReplace($aPath[$i], ' /.+', ''), '"*(.+\.\w+)', 1)
    ConsoleWrite('Suppir:  ')
    If Not @error Then
        ConsoleWrite($aMatches[0])
    EndIf
	ConsoleWrite(@CR)

    ; Yashied
    ConsoleWrite('Yashied: ' & _ExtractPath($aPath[$i]) & @CR)
    ConsoleWrite('--------------------------------------------------' & @CR)
Next

Func _ExtractPath($sPath)
    $sPath = StringStripWS($sPath, 7)
    If StringLeft($sPath, 1) = '"' Then
        $sPath = StringRegExpReplace($sPath, '\A"+|".*\z', '')
        If Not FileExists($sPath) Then
            $sPath = ''
        EndIf
    Else
        While Not FileExists($sPath)
            $sPath = StringLeft($sPath, StringInStr($sPath, ' ', 0, -1) - 1)
            If $sPath = '' Then
                ExitLoop
            EndIf
        WEnd
    EndIf
    Return $sPath
EndFunc   ;==>_ExtractPath



CreatoR, Suppir,

Можно составить универсальный pattern для этих примеров?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 159
Репутация
2 329
Yashied [?]
Можно составить универсальный pattern для этих примеров?
Это зависит от того, насколько данные примеры могут изменяться, тут попросту нужен ориентир, по которому будут проверяться дополнительные параметры в конце строки. Если например смотреть имя файла после слеша, то нужно не забывать что оно может(?) содержать пробелы, и тогда нужно искать другую опору, например точку и расширение имени файла:


Код:
Dim $aPath[8]

$aPath[0] = '"C:\Program Files\Unknown.dat\setup.exe" test.exe'
$aPath[1] = 'C:\Program Files\Unknown.dat\setup.exe test.exe'
$aPath[2] = 'C:\Program Files\Unknown.dat\setup.exe /d test.exe'
$aPath[3] = 'C:\Program Files\Unknown.dat\setup.exe test.exe /d'
$aPath[4] = 'C:\Program Files\Unknown.dat\setup.exe C:\#test.exe'
$aPath[5] = 'C:\Program Files\Unknown.dat\setup.exe #d C:\test.exe'
$aPath[6] = 'C:\Program Files\Unknown.dat\setup.exe test1.exe test2.exe'
$aPath[7] = 'C:\Program Files\Unknown.dat\setup.exe %1 -d -text.log'

$sPattern = '(?:"?)+(.*\\.*?\..*?)(?:"?)+ .*$'

For $i = 0 To UBound($aPath) - 1
    ConsoleWrite($i & ": " & StringRegExpReplace($aPath[$i], $sPattern, '\1') & @CR)
Next
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Так ведь супер получилось!!!

+1

Небольшое замечание, иногда файл может быть без пути, например

explorer.exe %1 -a -b ...
explorer.exe C:\Program Files\test.txt

Можно для этого написать pattern? Например для извлечения коммандной строки из реестра для кокого-нибудь типа файла.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 159
Репутация
2 329
Более удобный для разбора пример:

Код:
Dim $aPath[10]

$aPath[0] = '"C:\Program Files\Unknown.dat\setup.exe" test.exe'
$aPath[1] = 'C:\Program Files\Unknown.dat\setup.exe test.exe'
$aPath[2] = 'C:\Program Files\Unknown.dat\setup.exe /d test.exe'
$aPath[3] = 'C:\Program Files\Unknown.dat\setup.exe test.exe /d'
$aPath[4] = 'C:\Program Files\Unknown.dat\setup.exe C:\#test.exe'
$aPath[5] = 'C:\Program Files\Unknown.dat\setup.exe #d C:\test.exe'
$aPath[6] = 'C:\Program Files\Unknown.dat\setup.exe test1.exe test2.exe'
$aPath[7] = 'C:\Program Files\Unknown.dat\setup.exe %1 -d -text.log'
$aPath[8] = 'explorer.exe C:\Program Files\test.txt'
$aPath[9] = 'explorer.exe %1 -a -b ...'

$sQuotes_Pattern = '(?:"?)+' ;Кавычки (опционально, могут содержаться в множественном числе - подряд).
$sPath_Pattern = '((?:.*\\)?.*?\..*?)' ;Извлекаемый путь (с учётом точки и расширение имени файла).
$sParams_Pattern = ' (.*)$' ;Параметры (пробел после пути, и всё что после).

$sPattern = $sQuotes_Pattern & $sPath_Pattern & $sQuotes_Pattern & $sParams_Pattern
$sReplace = '\1' ;Замена (используется в закомментированном RegExpReplace), в данном случае нам нужна только первая группа, т.е извлекаемый путь

For $i = 0 To UBound($aPath) - 1
	$aRet = StringRegExp($aPath[$i], $sPattern, 3)
	
	ConsoleWrite("[" & $aPath[$i] & "]" & @LF)
	
	For $j = 0 To UBound($aRet)-1
		ConsoleWrite(@TAB & $j & ": " & $aRet[$j] & @LF)
	Next
	
;~ 	ConsoleWrite(@TAB & "[RegExpReplace] " & StringRegExpReplace($aPath[$i], $sPattern, $sReplace) & @CRLF)
	ConsoleWrite(@LF)
Next
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5 379
Репутация
2 702
Re: Извлечение полного имени папки RegExp\'ом, из нестандартного пути

Да это супер №3! Просто SDK какой-то!

+1 (нисколько не жалко)

:laugh:



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

Ну и последний вопрос на родственную тему. Нужно извлечь иконку (имя файла и индекс иконки). Возможны следующие варианты:

C:\MyProgram\Icons.dll,1
C:\MyProgram\Icons.dll , 1
Icons.dll, -4
Icons.dll, <= В этом случае индекс 0
Icons.dll <= Тоже 0
 
Верх