Что нового

Получение имени файла БЕЗ расширения

[email protected]@f

Новичок
Сообщения
44
Репутация
2
RegExp'ом не очень пользуюсь, но хотелось бы узнать, целесообразно ли использовать его в таком случае, когда необходимо из полного пути к файлу извлечь его имя без расширения?

Под целесообразностью имею ввиду быстроту и компактность кода.

Итог:

Самый быстрый способ с учётом всех нюансов и использованием строковых функций
Код:
$start=StringInStr($Path, "\", 0,-1)+1
    $name=StringMid($Path,$start,StringInStr($Path,".", 0,-1)-$start)


Самый быстрый способ с учётом всех нюансов и использованием RegExp
Код:
$name=StringRegExpReplace($Path, '^(?:.*\\)([^\\]*?)(?:\.[^.]+)?$', '\1')
 
Автор
P

[email protected]@f

Новичок
Сообщения
44
Репутация
2
Спасибо за способ через RegExp! :smile:
Но вопрос еще в силе, будет ли этот код выполняться быстрее?
 

AZJIO

Меценат
Меценат
Сообщения
2 752
Репутация
1 149
[email protected]@f

можешь тестом сравнить.

Код:
$Path='D:\Docum\File.txt'

$timer = TimerInit()
For $i = 1 to 10000
    $s=StringInStr($Path, "\", 0,-1)+1
    $tmp=StringMid($Path,$s,StringInStr($Path,".", 0,-1)-$s)
Next
MsgBox(0,$tmp, 'Время : '&Round(TimerDiff($timer), 2) & ' мсек')

$timer = TimerInit()
For $i = 1 to 10000
	$tmp=StringRegExpReplace($Path, '^(?:.*\\)([^\\]*?)(?:\.[^.]+)?$', '\1')
Next
MsgBox(0,$tmp, 'Время : '&Round(TimerDiff($timer), 2) & ' мсек')


Только нужно ещё модернизировать (уже модернизировал), а то бывают имена файлов с двумя точками.
 
Автор
P

[email protected]@f

Новичок
Сообщения
44
Репутация
2
Вот-вот. Через мой код это учтено.
У меня получается разница в 30 мсек. Но не добавит ли модернизация именно эти 30 мсек? :scratch:
 

gregaz

AutoIT Гуру
Сообщения
1 166
Репутация
299
AZJIO [?]
бывают имена файлов с двумя точками.
Одна из "бессмертных" ф-ий :
Код:
$sFullName="C:\13.Bulat_Okudzhava_-_Pesenka_O_Moskovskom_Metro.mp3"
$sFileNameNoExt = StringRegExpReplace(StringRegExpReplace($sFullName, "^.*\\", ""), '\.[^.]*$', '') ; Имя файла без расширения
ConsoleWrite ("$sFileNameNoExt = " & $sFileNameNoExt& @LF)
 

gregaz

AutoIT Гуру
Сообщения
1 166
Репутация
299
[email protected]@f [?]
Но таким образом скрипт отрабатывает дольше варианта без RegExp'a.
Естественно.
Стринговая ф-ия сработает наверняка быстрее.

Я привел пример , корректно работающего RegExp'a. Он составлен очень давно и вряд ли можно его упростить ,не теряя корректности.
 
Автор
P

[email protected]@f

Новичок
Сообщения
44
Репутация
2
dwerf [?]
Опытным путём обнаружено, что разница в скорости RegExp и прочих функций на разных версиях windows может изменяться.
Да, не говоря уже о том, что она может отличатся при каждом запуске и в зависимости от приоритета и количества запущенных фоновых приложений. Но и в той теме был определен оптимальный вариант как для XP, так и для 7 (первый).
 

AZJIO

Меценат
Меценат
Сообщения
2 752
Репутация
1 149
gregaz
Упростил, и исправил с учётом части из твоей регулярки, смотри пост с тестом времени.

[email protected]@f
Первый раз я тест неправильно сделал, смотри новый. В первом твоя регулярка изменяла поисковой шаблон, поэтому регулярка быстрее срабатывала.
 

gregaz

AutoIT Гуру
Сообщения
1 166
Репутация
299
AZJIO [?]
Упростил, и исправил с учётом части из твоей регулярки, смотри пост с тестом времени.
А я всегда считал,что в одном выражении этого не выполнить.
Кстати надо поправить для случая отсутствия пути :

Код:
$sText="13.-_Bulat_Okudzhava_-_Pesenka_O_Moskovskom_Metro.mp3"
$sPattern = '^(?:.*\\)?([^\\]*?)(?:\.[^.]+)?$'
 
Автор
P

[email protected]@f

Новичок
Сообщения
44
Репутация
2
Учёл отсутствие расширения, но тогда получается дольше :(
Код:
$t=StringInStr($Path, "\", 0,-1)+1
	$l=StringLen($Path)
	$p=StringInStr($Path,".", 0,-1,$l,$l-$t)
	If $p==0 Then	
		$tmp=StringMid($Path,$t)
	Else
		$tmp=StringMid($Path,$t,$p-$t)
	EndIf


Стало быть целесообразнее в моем случае использовать
Код:
StringRegExpReplace($Path, '^(?:.*\\)([^\\]*?)(?:\.[^.]+)?$', '\1')
?
gregaz [?]
Кстати надо поправить для случая отсутствия пути :
В моем случае не нужно.


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

Ан нет! Как оказалось, можно еще упростить, и тогда будет быстрее всех :blum:
Код:
$s=StringInStr($Path, "\", 0,-1)+1
    $tmp=StringMid($Path,$s,StringInStr($Path,".", 0,-1)-$s)
 

AZJIO

Меценат
Меценат
Сообщения
2 752
Репутация
1 149
[email protected]@f

А теперь перейдём к реальным результатам, попробуй такой тест:

Код:
; RecFileListToArray.au3 можно взять по ниже указанной ссылке
;http://www.autoitscript.com/forum/topic/126198-recfilelisttoarray-new-version-6-mar-11/
#include "RecFileListToArray.au3"
#include <Array.au3>

[email protected]

$aFile0 = _RecFileListToArray($Path, "*", 1, 1, 0, 2)
$aFile1=$aFile0


$timer = TimerInit()
For $i = 1 to $aFile0[0]
    $s=StringInStr($aFile0[$i], "\", 0,-1)+1
    $aFile0[$i]=StringMid($aFile0[$i],$s,StringInStr($aFile0[$i],".", 0,-1)-$s)
Next
_ArrayDisplay($aFile0, 'Время : '&Round(TimerDiff($timer), 2) & ' мсек')


$timer = TimerInit()
$tmp=''
For $i = 1 to $aFile1[0]
	$tmp&=$aFile1[$i]&@LF
Next
$aFile1=StringRegExp($tmp, '(?m)^(?:.*\\)([^\\]*?)(?:\.[^.]+)?$', 3)
_ArrayDisplay($aFile1, 'Время : '&Round(TimerDiff($timer), 2) & ' мсек')


Ведь нам не имеет смысла обрабатывать единичный случай, так как он достаточно быстрый и тут даже удобней простота записи, а вот обработка в цикле огромного массива здесь это важно. В итоге регулярное выражение отрабатывает быстрее, несмотря на то что я предварительно конвертировал массив в текст. Если заметишь задержку более указанное, то это медленно работает _ArrayDisplay :blum:
 
Автор
P

[email protected]@f

Новичок
Сообщения
44
Репутация
2
В моем случае необходимо обрабатывать только 1 файл, так что всё верно ;)

Кстати RecFileListToArray.au3 быстрее _FileListToArray?
 
Верх