Re: AHK: Регулярные выражения
Спасибо, уважаемые!
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Спасибо, уважаемые!
А с чего ты решил, что там "`n" ? Там `r.
А разве это имеет значение?
Если имеет, то первый пример на оффсайте неверен:
http://ahkscript.org/docs/commands/LoopReadFile.htm
Да и сама фраза тоже:
Remember to include a linefeed (`n) after the text, if desired
В твоем скрипте вижу следующие недочеты:
1) числа сравниваются, как числа.
2) скрипт неправильно работает с количеством букв, меньшим, чем n.
text=
(
a
б
3.0
003
)
N := 3, pos := 1
while pos := RegExMatch(text, "(.{" N "}).*?(\R|$)", match, pos + StrLen(match))
(prev == match1) ? NewText .= match : (prev := match1, NewText .= "_" . match)
msgbox % NewText
А разве это имеет значение?
Если имеет, то первый пример на оффсайте неверен
Имеет, наверно, только теоретически. Почему неверен? Там получают такой файл, какой нужен. В данном же случае это специально не оговаривалось.
Остальное легко исправляется, просто это тоже вряд ли имеет здесь значение.
while pos := RegExMatch(text, "([^\r\n]{1," N "}).*?(\R|$)", match, pos + StrLen(match))
(prev == "" . match1) ? NewText .= match : (prev := match1, NewText .= "_" . match)
Привет! Как захватить содержимое тегов div, но при этом, не более 100 символов? Т.е. следующие выделенные 100 символов:
<div class="pi_text">текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст</div>
Или следующие 37 символов, если в теге содержалось меньше 100 символов:
<div class="pi_text">текст текст текст текст текст текст т</div>
var1 := "<div class=""pi_text"">текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст</div>"
var2 := "<div class=""pi_text"">текст текст текст текст текст текст т</div>"
loop 2
{
RegExMatch(var%A_Index%, "<div class=""pi_text"">(?!</div>)((.(?!</div>)){0,99}.)(?=.*</div>)", match)
msgbox % match1
}
Спасибо большое! Возник по ходу вопрос: реально ли, именно посредством рег. выражений, получать это определенное количество символов в теге div, но чтобы граница получаемого текста не приходилась на текст в угловых скобках, т.е., чтобы как в примере ниже не отрезалось, а чтобы граница была до или после содержимого тегов? —
var1 := "<div class=""pi_text"">текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст <a href=""link""> текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст</div>"
var2 := "<div class=""pi_text"">текст текст текст текст текст текст т</div>"
loop 1
{
RegExMatch(var%A_Index%, "<div class=""pi_text"">(?!</div>)((.(?!</div>)){0,99}.)(?=.*</div>)", match)
msgbox % match1
}
Пробовал варианты с открывающей угловой скобкой в качестве максимальной границы, но всё не то.
а чтобы граница была до или после содержимого тегов?
Не понял. Покажите на примере, что вы хотите получить.
В идеале, чтобы получаемый текст (выделенный синим) не захватывал то, что в тегах, — когда максимальное значение приходится в пределы угловых скобок (тут граница до угл. скобки):
<div class=""pi_text"">текст текст текст текст текст текст текст текст <a href=""link""> текст текст<br> текст текст <a href=""link""> текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст
Или так (тут граница после угл. скобки в месте максимального диапазона):
<div class=""pi_text"">текст текст текст текст текст текст текст текст <a href=""link""> текст текст<br> текст текст <a href=""link""> текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст
Не так:
<div class=""pi_text"">текст текст текст текст текст текст текст текст <a href=""link""> текст текст<br> текст текст <a href=""link""> текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст
doc := ComObjCreate("htmlfile")
text = <div>654321</div>
doc.write(text)
doc.close()
MsgBox % SubStr(doc.body.innerText, 1, 3)
text = <div>аб<a href="http://script-coding.com">вг</a>де</div>
doc.write(text)
doc.close()
MsgBox % SubStr(doc.body.innerText, 1, 3)
var1 := "<div class=""pi_text"">текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст <a href=""link""> текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст текст</div>"
var2 := "<div class=""pi_text"">текст текст текст текст текст текст т</div>"
loop 2
{
RegExMatch(var%A_Index%, "<div class=""pi_text"">(?!</div>)((.(?!</div>)){0,99}.)(?=.*</div>)", match)
msgbox % RegExReplace(match1, "<[^>]*$")
}
shiz, ваш код не сохраняет в переменной теги между div.
А судя по выделенному синим это необходимо.
Malcev, не уверен, что необходимо, иначе может получиться, что будет захвачен открывающий тег без закрывающего.
Спасибо, нужно было именно регулярное выражение. На всякий случай: может дано представить на них обработку из следующих двух строк — единым выражением? —
RegExMatch(var%A_Index%, "<div class=""pi_text"">(?!</div>)((.(?!</div>)){0,99}.)(?=.*</div>)", match)
msgbox % RegExReplace(match1, "<[^>]*$")
…иначе может получиться, что будет захвачен открывающий тег без закрывающего.
Как понимаю, не по теме, но на этом пути можно было бы получить и HTML-теги с закрытием тех, содержимое которых захвачено не полностью (правда «нормализованные» IE по-своему):
doc := ComObjCreate("htmlfile")
text = <div>аб<a href="http://script-coding.com">вг</a>де</div>
doc.write(text)
doc.close()
TextRange := doc.selection.createRange()
; TextRange.moveStart("character", 0)
TextRange.moveEnd("character", 3)
MsgBox % TextRange.htmlText
По какой причине, при чтении файла (ANSI), не отрабатывает замена любых знаков на `n, хотя если содержимое файла добавить в виде переменной в скрипт, то замены производятся?
Srt := RegExReplace(Srt, "`t", "`n")
Srt := RegExReplace(Srt, "\t", "\n")
Задам свой вопрос сюда, вместо создания новой темы, ибо заголовок соответствует. Если я был не прав, да простят меня модераторы.
Собственно у меня в текстовом файле есть строка:
+ Nick_Name - Reason
Мне нужно с помощью RegExReplace (это важно), присвоить переменные + Nick_Name и Reason. Соответственно - не брать в переменную. Мой гуру-наставник по AHK просто не может сейчас мне помочь, а он меня научил выделять в этой функции только что-то до или после определенного символа.
DD
Первая строка должна работать без проблем. Вторая нет, т.к. в строке замены Escape-последовательности не указываются.
присвоить переменные ... не брать в переменную
Нормальным языком, пожалуйста.
Соответственно тире не брать в переменную. Так понятно? У меня в результате, грубо говоря, var1 = "+" var2 = "Nick_Name" var3 = "Reason" должно выйти.
Src = Isdfmnc_Fldscnqwo_1:805 "`n" "asdfasdfasdfasdfasdfasdfasdfasdf"
Var := RegExMatch(Src, "\:.*$", Found) ; Как сделать что-бы Found вернул "805"
MsgBox, % Found
Подскажите пожалуйста, как сделать что-бы Found вернул "805"?
belyankin12
Так годится?:
Str := "+ Nick_Name - Reason"
Var := StrSplit(RegExReplace(Str, "( -?)+", "|"), "|")
MsgBox, % Var.1 "`n" Var.2 "`n" Var.3
Loop % Var.MaxIndex()
MsgBox, % Var[a_index]
migomigo
Src = Isdfmnc_Fldscnqwo_1:805 "`n" "asdfasdfasdfasdfasdfasdfasdfasdf"
Var := RegExMatch(Src, "\:(\d+)", Found)
MsgBox, % Found1
Found := RegExReplace(Src, ".+\:(\d+).+", "$1")
MsgBox, % Found
Flasher
Вот так:
Src = Isdfmnc_Fldscnqwo_1:805 "`n" "asdfasdfasdfasdfasdfasdfasdfasdf"
Found := RegExReplace(Src, ".+\:(\d+).+", "$1")
MsgBox, % Found
работает идеально.
А вот так:
Src1 := "Time_Limits_1:605"
Found1 := RegExReplace(Src1, ".+\:(\d+).+", "$1") ;= Возвращяет цыфру в строе после знака ":"
MsgBox, % Found1
теряет последнюю цифру.
migomigo
Я же не в курсе вариаций. В строке поиска вместо + нужна * на конце.
Спасибо.
Flasher, почему-то я думал, что это очевидно, но похоже я был не прав. На месте + может стоять и - и = . Мне нужна переменная, которая её выведет а в зависимости от того, что там стоит, я уже буду условие делать.
Давайте по-другому объясню. У меня сейчас есть запись такого вида:
Nick_Name - Reason
Вывожу переменные я так:
UnName := RegExReplace(line, "\ -.*", "")
UnReson := RegExReplace(line, ".*-", "")
А я хочу, чтобы у меня было все тоже самое, только я мог записать + - или = в строчку ("+ Nick_Name - Reason") и в зависимости от того, что там стоит, развивать условие. Nick_Name может быть любым, но у него обязательно есть _ между параметром Nick и Name. Reason тоже может быть разным, но он всегда стоит после тире и одного пробела.
Соответственно в конкретно этом случае переменная UnName должна быть равна "Nick_Name", переменная UnReason = "Reason", а какая-то переменная var = "+" "-" или "=", в зависимости от того, что там стоит.
Мой гуру-наставник как-то мне объяснял о RegExReplace, что можно ловить текст в переменную не только до или после определенного символа (как я сейчас вылавливаю переменную), но и внутри текста, между двумя какими-то символами, но я был невнимательным .
Приведете полные примеры строк и что вы хотите получить.
belyankin12
Убрал первые '-?' из подвыражения. Этого достаточно?
Malcev, Я вам запишу это так, как я умею, через RegExMatch, а вы преобразуете это в RegExReplace, с сохранением имен переменных.
line := "+ Nick_Name - Reason"
if RegExMatch(line, "(.*) (.*) - (.*)", end_str)
UnName := end_str2
UnReason := end_str3
var := end_str1
if (var = "+") {
msgbox, Плюс
} else if (var = "=") {
msgbox, Равно
} else if (var = "-") {
msgbox, Минус
}
Flasher, да, так работает, но я ничего совсем не понимаю в вашем коде. Могли бы вы сделать его пусть и нерациональным, но более понятным? Без объединения всех переменных сплитом, а созданию трех разных переменных.
А чем вас ваш вариант не устраивает?
Malcev, я задал этот вопрос не потому что не могу решить проблему, а потому, что я не знаю как пользоваться RegExReplace. На таком простом примере я смогу понять некие азы, ведь есть моменты, когда ExReplace сработает лучше, чем ExMatch (не зря же эту команду придумали), а кроме вас, больше мне некого спросить .
А он для вашего случая и не преднозначен.
Когда вам понадобится что-то заменить, тогда его и используйте.
Replace - замена.
Match - совпадение.
Вы не поняли, я пытаюсь сейчас с помощью ExReplace научится находить совпадения. А в будущем это мне может понадобится, когда понадобится замену производить (чтобы в таком случае не использовать сначала ExMatch а потом ExReplace).
Ту проблему, что я показал вам, я решил давно уже с помощью ExMatch. Но знаниям же предела нет .
belyankin12
А что именно непонятно?
Str := "+ Nick_Name - Reason"
Var := RegExReplace(Str, "( -?)+", "|") ; замена пробела или комбинации пробела с '-' на |
Var := StrSplit(Var, "|") ; массив по сепаратору "|"
MsgBox, % Var.1
MsgBox, % Var.2
MsgBox, % Var.3
Flasher, вот посмотрите, как я понимаю то, что тут написано. Все, что до - идёт (+ Nick_Name ) заменяется на |, а потом идёт команда StrSplit, назначение которой я могу примерно перевести, что это соединяет строки между собой она. Непонятно откуда скрипт по отдельности выводит + и Nick_Name. Ну и непонятно, откуда скрипт узнает параметр Reason.
Flasher, способ ненадежный, так как в нике может быть символ "|".
belyankin12
Там же в комментарии написано "пробела или комбинации пробела с '-'". Поэтому "Все, что до - идёт (+ Nick_Name )" неверно. Пробел есть между плюсом и Nick_Name? Есть. Так же, есть пробел до Reason.
Malcev
Не встречал таких ников. Ну, можно | на `r заменить, не суть.
Flasher, часть понял. Т.е. после ExReplace выражение в памяти сохранилось так:
+|Nick_Name|Reason
Верно? Если я прав, я уже логически понимаю как работает strsplit, он просто создает массив с переменными до первого |, после первого и до второго | и после второго |. Так?
belyankin12
Примерно. Строка сохранилась в переменной Var, далее она преобразуется в массив, разбивая строку по заданному разделителю. Разделителей всегда на один меньше, чем создаваемых элементов массива.
Все понятно, спасибо.
Подскажите пожалуйста!
var =
(
Time_Limits_1:В Контакте
ВКонтакте
Берлога - Чат
Однокласники
@Mail.ru
порно
сериал
Home - ROBLOX
ok.ru
http://worldoftanks.ru
ROBLOX
)
RegExReplace_var := RegExReplace(var, "", "$1")
; Как убрать в начале переменной "Time_Limits_1:"
; что-бы получилось:
RegExReplace_var =
(
В Контакте
ВКонтакте
Берлога - Чат
Однокласники
@Mail.ru
порно
сериал
Home - ROBLOX
ok.ru
http://worldoftanks.ru
ROBLOX
)
migomigo
RegExReplace_var = % SubStr(var, 15)
; либо:
RegExReplace_var := RegExReplace(var, "^\w+:")
Flasher
Спасибо, то что надо.
С каким шаблоном удалить из списка папки, дублирующие имеющиеся в списке папки с файлами, т.е. выделенные? —
C:\IE
C:\IE\t=27229.html
C:\Temp\FXSAPIDebugLogFile.txt
C:\Temp\flashgot.Profile\FlashGot.exe
C:\Temp\flashgot.Profile
C:\Program Files\Common Files\System
C:\Program Files\Common Files
F:\APPs\AdvOR-0.3.0.20\AdvOR\AdvOR.ini
InStr() в цикле - расчет за N² операций (если самый простой алгоритм — проверить вхождение каждого элемента в каждом), где N — длина списка.
Причем тут RegEx?
Для начала нужно определиться, что считать за файл, а что за директорию, так как:
C:\Program Files\Common Files\System - может быть файлом.
C:\Temp\flashgot.Profile\FlashGot.exe - может быть директорией.
Malcev, судя по примеру, нет нужды различать папки и файлы,
просто оставить элемент с самым длинным путем, элементы с входящими в него путями — удалить.
Malcev
Возможно, по атрибутам объектов, которые можно проверять, выделив пары? Но в моём случае это не требуется, потому что там пути с разницей в уровень, всегда будут файлом и папкой.
stealzy, если бы было так, то C:\Program Files\Common Files было бы выделенным.
DD, разве?
C:\Program Files\Common Files\System
C:\Program Files\Common Files
DD, ну да, System очевидно файл.
Наверно вам стоит новую тему начать.
Malcev, ей-Богу))
stealzy, похоже, что вам не стоит советовать, потому что System — папка, а с RegEx тоже можно сделать, хотя и не принципиально)).
Malcev, то есть, System — это просто пример, который указал, чтобы не было ориентации на расширение и которую надо считать за файл. Таким образом, удаляется всё, у чего есть дубликат — уровнем выше.
Без предварительной сортировки не знаю как:
var=
(
C:\IE
C:\IE\t=27229.html
C:\Temp\FXSAPIDebugLogFile.txt
C:\Temp\flashgot.Profile\FlashGot.exe
C:\Temp\flashgot.Profile
C:\Program Files\Common Files\System
C:\Program Files\Common Files
F:\APPs\AdvOR-0.3.0.20\AdvOR\AdvOR.ini
)
Sort var
msgbox % RegExReplace(var,"sm`a)^(.+)\R(?=.*\1\\)")
По простецкому так наверное:
var=
(
C:\IE
C:\IE\t=27229.html
C:\Temp\FXSAPIDebugLogFile.txt
C:\Temp\flashgot.Profile\FlashGot.exe
C:\Temp\flashgot.Profile
C:\Program Files\Common Files\System
C:\Program Files\Common Files
F:\APPs\AdvOR-0.3.0.20\AdvOR\AdvOR.ini
)
Loop, Parse, var, `n
If !InStr("`n" var, "`n" A_LoopField "\")
List .= (List = "" ? "" : "`n") A_LoopField
MsgBox % List
Malcev а что значит "1" в шаблоне, совпадение первого подшаблона? И .* не лишнее?
serzh82saratov, да, совпадение первого подшаблона.
.* не лишнее, например, в таком случае:
var=
(
C:\IE
C:\IE.
C:\IE\t=27229.html
)
Sort var
msgbox % RegExReplace(var,"sm`a)^(.+)\R(?=.*\1\\)")
Спасибо!
var=
(
C:\Temp\flashgot.Profile
C:\IE
C:\Program Files\Common Files
C:\Temp\FXSAPIDebugLogFile.txt
C:\Program Files\Common Files\System
C:\Temp\flashgot.Profile\FlashGot.exe
F:\APPs\AdvOR-0.3.0.20\AdvOR\AdvOR.ini
C:\IE\t=27229.html
)
MsgBox, % RegExReplace(var,"sm`a)^(.+)\\.*\K^\1(\R|$)|^(.+)(\R|$)(?=.*^\3\\)")
Аа-а, без сортировки. Спасибо, круто.
teadrinker интересный шаблон, если не сложно можешь рассказать что да как в нём.
RegExReplace(var,"sm`a)^(.+)\\.*\K^\1(\R|$)|^(.+)(\R|$)(?=.*^\3\\)")
Если s в опциях — точка означает любой символ, включая любые возможные переносы строк.
m`a — символы ^ и $ означают начало и конец строк (а не начало и конец шаблона).
^(.+)\\.*\K — часть перед \K не включается в замену, а только говорит о том, что должно быть в начале.
\1 — ссылки на подшаблоны по порядковому номеру.
Подскажите, пожалуйста, как от заголовка страницы оставить только название темы?
До:
AHK: Регулярные выражения (Страница 7) — AutoHotkey — Общение — Серый форум - Google Chrome
После:
Регулярные выражения
Header = AHK: Регулярные выражения (Страница 7) — AutoHotkey — Общение — Серый форум - Google Chrome
msgbox % RegExReplace(Header, "[\w: ]*([^(]+) \(.+", "$1")
Выражение слева направо: необязательное множество в квадратных скобках любой латиницы, двоеточия и пробела, подвыражение в скобках из множества любых символов, отличных от открывающей скобки, далее - пробел, сама скобка и множество любых символов. В $1 попадает всё, что попало в подвыражение.
Flasher, спасибо! Это выражение будет работать с любыми темами из данной ветки? Могли бы Вы добавить комментарии ко второй строке?
becauseim
Теперь да. Добавил.
Это выражение будет работать с любыми темами из данной ветки?
Конечно нет.
Правильно так:
Header = AHK: IfWinNotActive для всех полноэкранных приложений (Страница 1) — AutoHotkey — Общение — Серый форум - Google Chrome
msgbox % RegExReplace(Header, "(AHK: ?)?([^(]+) \(.+", "$2")
Flasher, к сожалению не успел прочитать, что вы ответили, так как всё уже потёрто.
Кстати, ваш код неверен:
Header = AHK: Sockets (Страница 1) — AutoHotkey — Общение — Серый форум - Google Chrome
msgbox % RegExReplace(Header, "[\w: ]*([^(]+) \(.+", "$1")
Flasher, спасибо за комментарии! Но если в названии темы идут слова на латинице или цифры, то они не выводятся. В варианте от teadrinker такого не наблюдается.
teadrinker, если несложно, добавьте коментарии к Вашему варианту.
Ну у teadrinkera тоже не идеальный вариант.
Header = AHK: Перенести содержимое переменной (Loop, Parse) (Страница 1) — AutoHotkey — Общение — Серый форум - Google Chrome
msgbox % RegExReplace(Header, "(AHK: ?)?([^(]+) \(.+", "$2")
Я бы сделал так:
Header = AHK: Перенести содержимое переменной (Loop, Parse) (Страница 1) — AutoHotkey — Общение — Серый форум - Google Chrome
msgbox % RegExReplace(Header, "AHK:\s*(.*) \(Страница.*", "$1")
Malcev
Во всех случаях проблемы. Тогда уж так:
Header = Восстановление подключения Интернет при обрыве связи (Страница 1) — AutoHotkey — Общение — Серый форум
msgbox % RegExReplace(Header, "i)(AHK:\s*)?(.*) \(Страница \d+\) — .*", "$2")
И, полагаю, всё же лучше забирать не из заголовка, а из кода в <h1 class="main-title">.
Flasher, спасибо! Последний вариант выглядит значителньо иначе. Дайте комментарии к нему, пожалуйста. Желательно с видимым разделением.
"i) Описание
(AHK:\ Описание
s*)?(.*) \ Описание
(Страница \
d+\
) — .*", "$2")
becauseim
Мне кажется, проще будет, если напишите, что именно неясно, исходя из справочной информации.
Во всех случаях проблемы.
Ну я бы назвал их исключениями, а не случаями.
Их, кстати, гораздо больше: AutoHotKey:, AHK_L:,WSH or AHK:....
Возможно кто-нибудь AHK напишет кириллицей (АНК) дабы не менять язык.
Всех все-равно не учтёшь.
Можно так:
Header = AutoHotKey: Передача указателя между двумя процессами (скриптами) (Страница 1) — AutoHotkey — Общение — Серый форум
msgbox % RegExReplace(Header, "(.*?(:|-)\s*)?(.*) \(Страница.*", "$3")
полагаю, всё же лучше забирать не из заголовка, а из кода в <h1 class="main-title">.
А разница?
Ну я бы назвал их исключениями, а не случаями.
Я их называю кодами.
Всех все-равно не учтёшь.
Можно так: ([\wА-я]*:\s*)?
А разница?
Там только заголовок темы, без "мусора".
Мусор-то как-раз несложно убрать (легче, чем получить его из кода страницы).
Вариант кода из 72 поста вроде работает, (если, конечно, не брать во внимание темы без префикса , но с двоеточим либо тире).
Но таких я на форуме беглым взглядом не нашёл.
Вообще кроме - там может быть и —. Да и пробельные символы в префиксе лучше исключить: [^\s]*.
Пробельные символы не надо исключать, а вот цифры стоит:
Header = WSH or AHK: Копирование выделенных ссылок (Страница 1) — AutoHotkey — Общение — Серый форум
msgbox % RegExReplace(Header, "(\D*?(:|-|—)\s*)?(.*) \(Страница.*", "$3")
Цифры тоже нужны: AU3 вместо AutoIt.
Тогда так:
Header = WSH or AHK: Копирование выделенных ссылок (Страница 1) — AutoHotkey — Общение — Серый форум
msgbox % RegExReplace(Header, "(.*?(:|-|—)\s*)?(.*)(?= \(Страница).*", "$3")
Всё-равно проблемы с этим дефисом. Скажем, в комьюнити заголовок "Веб-сайт www.blabla.org возвращает 404".
Судя по всему автора интересует только данная ветка:
Это выражение будет работать с любыми темами из данной ветки?
Можно убрать "в комьюнити", суть не изменится.
WSH or AHK - это ведь тоже что-то с чем-то.
Header = Веб-сайт www.blabla.org возвращает 404 (Страница 1) — AutoHotkey — Общение — Серый форум
msgbox % RegExReplace(Header, "i)(.*?(ahk|autohotkey|анк).*?(:|-|—)\s*)?(.*)(?= \(Страница).*", "$4")
.*?(.|анк).*? - это зачем? Могут быть Танки, Банкнота, Анкета и т.д.
Для таких случаев.
Вставил границы:
Header = АНК: Отслеживание "родного" или текущего разрешения экрана (Страница 1) — AutoHotkey — Общение — Серый форум
msgbox % RegExReplace(Header, "i)(*UCP)(.*?(ahk|autohotkey|\bанк\b).*?(:|-|—)\s*)?(.*)(?= \(Страница).*", "$4")
Подскажите, пожалуйста, как удалить первые три строки и первые три символа из четвертой строки? Результат в данном случае должен выдать три нуля.
Пытался удалить строки с помощью TF.ahk, но не получается. Первое значение функции вводил по-разному, в кавычках и без.
/*
Name : TF: Textfile & String Library for AutoHotkey
Version : 3.6
Documentation : https://github.com/hi5/TF
AHKScript.org : http://www.ahkscript.org/boards/viewtopic.php?f=6&t=576
AutoHotkey.com: http://www.autohotkey.com/forum/topic46195.html (Also for examples)
License : see license.txt
Credits & History: See documentation at GH above.
Structure of most functions:
TF_...(Text, other parameters)
{
; get the basic data we need for further processing and returning the output:
TF_GetData(OW, Text, FileName)
; OW = 0 Copy inputfile
; OW = 1 Overwrite inputfile
; OW = 2 Return variable
; Text : either contents of file or the var that was passed on
; FileName : Used in case OW is 0 or 1 (=file), not used for OW=2 (variable)
; Creates a matchlist for use in Loop below
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; A_ThisFunc useful for debugging your scripts
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
...
}
Else
{
...
}
}
; either copy or overwrite file or return variable
Return TF_ReturnOutPut(OW, OutPut, FileName, TrimTrailing, CreateNewFile)
; OW 0 or 1 = file
; Output = new content of file to save or variable to return
; FileName
; TrimTrailing: because of the loops used most functions will add trailing newline, this will remove it by default
; CreateNewFile: To create a file that doesn't exist this parameter is needed, only used in few functions
}
*/
TF_CountLines(Text)
{
TF_GetData(OW, Text, FileName)
StringReplace, Text, Text, `n, `n, UseErrorLevel
Return ErrorLevel + 1
}
TF_ReadLines(Text, StartLine = 1, EndLine = 0, Trailing = 0)
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
OutPut .= A_LoopField "`n"
Else if (A_Index => EndLine)
Break
}
OW = 2 ; make sure we return variable not process file
Return TF_ReturnOutPut(OW, OutPut, FileName, Trailing)
}
TF_ReplaceInLines(Text, StartLine = 1, EndLine = 0, SearchText = "", ReplaceText = "")
{
TF_GetData(OW, Text, FileName)
IfNotInString, Text, %SearchText%
Return Text ; SearchText not in TextFile so return and do nothing, we have to return Text in case of a variable otherwise it would empty the variable contents bug fix 3.3
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
StringReplace, LoopField, A_LoopField, %SearchText%, %ReplaceText%, All
OutPut .= LoopField "`n"
}
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_Replace(Text, SearchText, ReplaceText="")
{
TF_GetData(OW, Text, FileName)
IfNotInString, Text, %SearchText%
Return Text ; SearchText not in TextFile so return and do nothing, we have to return Text in case of a variable otherwise it would empty the variable contents bug fix 3.3
Loop
{
StringReplace, Text, Text, %SearchText%, %ReplaceText%, All
if (ErrorLevel = 0) ; No more replacements needed.
break
}
Return TF_ReturnOutPut(OW, Text, FileName, 0)
}
TF_RegExReplaceInLines(Text, StartLine = 1, EndLine = 0, NeedleRegEx = "", Replacement = "")
{
options:="^[imsxADJUXPS]+\)" ; Hat tip to sinkfaze http://www.autohotkey.com/forum/viewtopic.php?t=60062
If RegExMatch(searchText,options,o)
searchText := RegExReplace(searchText,options,(!InStr(o,"m") ? "m$0" : "$0"))
Else searchText := "m)" . searchText
TF_GetData(OW, Text, FileName)
If (RegExMatch(Text, SearchText) < 1)
Return Text ; SearchText not in TextFile so return and do nothing, we have to return Text in case of a variable otherwise it would empty the variable contents bug fix 3.3
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
LoopField := RegExReplace(A_LoopField, NeedleRegEx, Replacement)
OutPut .= LoopField "`n"
}
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_RegExReplace(Text, NeedleRegEx = "", Replacement = "")
{
options:="^[imsxADJUXPS]+\)" ; Hat tip to sinkfaze http://www.autohotkey.com/forum/viewtopic.php?t=60062
if RegExMatch(searchText,options,o)
searchText := RegExReplace(searchText,options,(!InStr(o,"m") ? "m$0" : "$0"))
else searchText := "m)" . searchText
TF_GetData(OW, Text, FileName)
If (RegExMatch(Text, SearchText) < 1)
Return Text ; SearchText not in TextFile so return and do nothing, we have to return Text in case of a variable otherwise it would empty the variable contents bug fix 3.3
Text := RegExReplace(Text, NeedleRegEx, Replacement)
Return TF_ReturnOutPut(OW, Text, FileName, 0)
}
TF_RemoveLines(Text, StartLine = 1, EndLine = 0)
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
Continue
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_RemoveBlankLines(Text, StartLine = 1, EndLine = 0)
{
TF_GetData(OW, Text, FileName)
If (RegExMatch(Text, "[\S]+?\r?\n?") < 1)
Return Text ; No empty lines so return and do nothing, we have to return Text in case of a variable otherwise it would empty the variable contents bug fix 3.3
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
OutPut .= (RegExMatch(A_LoopField,"[\S]+?\r?\n?")) ? A_LoopField "`n" :
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_RemoveDuplicateLines(Text, StartLine = 1, Endline = 0, Consecutive = 0, CaseSensitive = false)
{
TF_GetData(OW, Text, FileName)
If (StartLine = "")
StartLine = 1
If (Endline = 0 OR Endline = "")
EndLine := TF_Count(Text, "`n") + 1
Loop, Parse, Text, `n, `r
{
If (A_Index < StartLine)
Section1 .= A_LoopField "`n"
If A_Index between %StartLine% and %Endline%
{
If (Consecutive = 1)
{
If (A_LoopField <> PreviousLine) ; method one for consecutive duplicate lines
Section2 .= A_LoopField "`n"
PreviousLine:=A_LoopField
}
Else
{
If !(InStr(SearchForSection2,"__bol__" . A_LoopField . "__eol__",CaseSensitive)) ; not found
{
SearchForSection2 .= "__bol__" A_LoopField "__eol__" ; this makes it unique otherwise it could be a partial match
Section2 .= A_LoopField "`n"
}
}
}
If (A_Index > EndLine)
Section3 .= A_LoopField "`n"
}
Output .= Section1 Section2 Section3
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_InsertLine(Text, StartLine = 1, Endline = 0, InsertText = "")
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
Output .= InsertText "`n" A_LoopField "`n"
Else
Output .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_ReplaceLine(Text, StartLine = 1, Endline = 0, ReplaceText = "")
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
Output .= ReplaceText "`n"
Else
Output .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_InsertPrefix(Text, StartLine = 1, EndLine = 0, InsertText = "")
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
OutPut .= InsertText A_LoopField "`n"
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_InsertSuffix(Text, StartLine = 1, EndLine = 0 , InsertText = "")
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
OutPut .= A_LoopField InsertText "`n"
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_TrimLeft(Text, StartLine = 1, EndLine = 0, Count = 1)
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
StringTrimLeft, StrOutPut, A_LoopField, %Count%
OutPut .= StrOutPut "`n"
}
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_TrimRight(Text, StartLine = 1, EndLine = 0, Count = 1)
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
StringTrimRight, StrOutPut, A_LoopField, %Count%
OutPut .= StrOutPut "`n"
}
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_AlignLeft(Text, StartLine = 1, EndLine = 0, Columns = 80, Padding = 0)
{
Trim:=A_AutoTrim ; store trim settings
AutoTrim, On ; make sure AutoTrim is on
TF_GetData(OW, Text, FileName)
If (Endline = 0 OR Endline = "")
EndLine := TF_Count(Text, "`n") + 1
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
LoopField = %A_LoopField% ; Make use of AutoTrim, should be faster then a RegExReplace. Trims leading and trailing spaces!
SpaceNum := Columns-StrLen(LoopField)-1
If (SpaceNum > 0) and (Padding = 1) ; requires padding + keep padding
{
Left:=TF_SetWidth(LoopField,Columns, 0) ; align left
OutPut .= Left "`n"
}
Else
OutPut .= LoopField "`n"
}
Else
OutPut .= A_LoopField "`n"
}
AutoTrim, %Trim% ; restore original Trim
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_AlignCenter(Text, StartLine = 1, EndLine = 0, Columns = 80, Padding = 0)
{
Trim:=A_AutoTrim ; store trim settings
AutoTrim, On ; make sure AutoTrim is on
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
LoopField = %A_LoopField% ; Make use of AutoTrim, should be faster then a RegExReplace
SpaceNum := (Columns-StrLen(LoopField)-1)/2
If (Padding = 1) and (LoopField = "") ; skip empty lines, do not fill with spaces
{
OutPut .= "`n"
Continue
}
If (StrLen(LoopField) >= Columns)
{
OutPut .= LoopField "`n" ; add as is
Continue
}
Centered:=TF_SetWidth(LoopField,Columns, 1) ; align center using set width
OutPut .= Centered "`n"
}
Else
OutPut .= A_LoopField "`n"
}
AutoTrim, %Trim% ; restore original Trim
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_AlignRight(Text, StartLine = 1, EndLine = 0, Columns = 80, Skip = 0)
{
Trim:=A_AutoTrim ; store trim settings
AutoTrim, On ; make sure AutoTrim is on
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
LoopField = %A_LoopField% ; Make use of AutoTrim, should be faster then a RegExReplace
If (Skip = 1) and (LoopField = "") ; skip empty lines, do not fill with spaces
{
OutPut .= "`n"
Continue
}
If (StrLen(LoopField) >= Columns)
{
OutPut .= LoopField "`n" ; add as is
Continue
}
Right:=TF_SetWidth(LoopField,Columns, 2) ; align right using set width
OutPut .= Right "`n"
}
Else
OutPut .= A_LoopField "`n"
}
AutoTrim, %Trim% ; restore original Trim
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
; Based on: CONCATenate text files, ftp://garbo.uwasa.fi/pc/ts/tsfltc22.zip
TF_ConCat(FirstTextFile, SecondTextFile, OutputFile = "", Blanks = 0, FirstPadMargin = 0, SecondPadMargin = 0)
{
If (Blanks > 0)
Loop, %Blanks%
InsertBlanks .= A_Space
If (FirstPadMargin > 0)
Loop, %FirstPadMargin%
PaddingFile1 .= A_Space
If (SecondPadMargin > 0)
Loop, %SecondPadMargin%
PaddingFile2 .= A_Space
Text:=FirstTextFile
TF_GetData(OW, Text, FileName)
StringSplit, Str1Lines, Text, `n, `r
Text:=SecondTextFile
TF_GetData(OW, Text, FileName)
StringSplit, Str2Lines, Text, `n, `r
Text= ; clear mem
; first we need to determine the file with the most lines for our loop
If (Str1Lines0 > Str2Lines0)
MaxLoop:=Str1Lines0
Else
MaxLoop:=Str2Lines0
Loop, %MaxLoop%
{
Section1:=Str1Lines%A_Index%
Section2:=Str2Lines%A_Index%
OutPut .= Section1 PaddingFile1 InsertBlanks Section2 PaddingFile2 "`n"
Section1= ; otherwise it will remember the last line from the shortest file or var
Section2=
}
OW=1 ; it is probably 0 so in that case it would create _copy, so set it to 1
If (OutPutFile = "") ; if OutPutFile is empty return as variable
OW=2
Return TF_ReturnOutPut(OW, OutPut, OutputFile, 1, 1)
}
TF_LineNumber(Text, Leading = 0, Restart = 0, Char = 0) ; HT ribbet.1
{
global t
TF_GetData(OW, Text, FileName)
Lines:=TF_Count(Text, "`n") + 1
Padding:=StrLen(Lines)
If (Leading = 0) and (Char = 0)
Char := A_Space
Loop, %Padding%
PadLines .= Char
Loop, Parse, Text, `n, `r
{
If Restart = 0
MaxNo = %A_Index%
Else
{
MaxNo++
If MaxNo > %Restart%
MaxNo = 1
}
LineNumber:= MaxNo
If (Leading = 1)
{
LineNumber := Padlines LineNumber ; add padding
StringRight, LineNumber, LineNumber, StrLen(Lines) ; remove excess padding
}
If (Leading = 0)
{
LineNumber := LineNumber Padlines ; add padding
StringLeft, LineNumber, LineNumber, StrLen(Lines) ; remove excess padding
}
OutPut .= LineNumber A_Space A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
; skip = 1, skip shorter lines (e.g. lines shorter startcolumn position)
; modified in TF 3.4, fixed in 3.5
TF_ColGet(Text, StartLine = 1, EndLine = 0, StartColumn = 1, EndColumn = 1, Skip = 0)
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
If (StartColumn < 0)
{
StartColumn++
Loop, Parse, Text, `n, `r ; parsing file/var
{
If A_Index in %TF_MatchList%
{
output .= SubStr(A_LoopField,StartColumn) "`n"
}
else
output .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
if RegExMatch(StartColumn, ",|\+|-")
{
StartColumn:=_MakeMatchList(Text, StartColumn, 1, 1)
Loop, Parse, Text, `n, `r ; parsing file/var
{
If A_Index in %TF_MatchList%
{
loop, parse, A_LoopField ; parsing LINE char by char
{
If A_Index in %StartColumn% ; if col in index get char
output .= A_LoopField
}
output .= "`n"
}
else
output .= A_LoopField "`n"
}
output .= A_LoopField "`n"
}
else
{
EndColumn:=(EndColumn+1)-StartColumn
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
StringMid, Section, A_LoopField, StartColumn, EndColumn
If (Skip = 1) and (StrLen(A_LoopField) < StartColumn)
Continue
OutPut .= Section "`n"
}
}
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
; Based on: COLPUT.EXE & CUT.EXE, ftp://garbo.uwasa.fi/pc/ts/tsfltc22.zip
; modified in TF 3.4
TF_ColPut(Text, Startline = 1, EndLine = 0, StartColumn = 1, InsertText = "", Skip = 0)
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
If RegExMatch(StartColumn, ",|\+")
{
StartColumn:=_MakeMatchList(Text, StartColumn, 0, 1)
Loop, Parse, Text, `n, `r ; parsing file/var
{
If A_Index in %TF_MatchList%
{
loop, parse, A_LoopField ; parsing LINE char by char
{
If A_Index in %StartColumn% ; if col in index insert text
output .= InsertText A_LoopField
Else
output .= A_LoopField
}
output .= "`n"
}
else
output .= A_LoopField "`n"
}
output .= A_LoopField "`n"
}
else
{
StartColumn--
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
If (StartColumn > 0)
{
StringLeft, Section1, A_LoopField, StartColumn
StringMid, Section2, A_LoopField, StartColumn+1
If (Skip = 1) and (StrLen(A_LoopField) < StartColumn)
OutPut .= Section1 Section2 "`n"
}
Else
{
Section1:=SubStr(A_LoopField, 1, StrLen(A_LoopField) + StartColumn + 1)
Section2:=SubStr(A_LoopField, StrLen(A_LoopField) + StartColumn + 2)
If (Skip = 1) and (A_LoopField = "")
OutPut .= Section1 Section2 "`n"
}
OutPut .= Section1 InsertText Section2 "`n"
}
Else
OutPut .= A_LoopField "`n"
}
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
; modified TF 3.4
TF_ColCut(Text, StartLine = 1, EndLine = 0, StartColumn = 1, EndColumn = 1)
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
If RegExMatch(StartColumn, ",|\+|-")
{
StartColumn:=_MakeMatchList(Text, StartColumn, EndColumn, 1)
Loop, Parse, Text, `n, `r ; parsing file/var
{
If A_Index in %TF_MatchList%
{
loop, parse, A_LoopField ; parsing LINE char by char
{
If A_Index not in %StartColumn% ; if col not in index get char
output .= A_LoopField
}
output .= "`n"
}
else
output .= A_LoopField "`n"
}
output .= A_LoopField "`n"
}
else
{
StartColumn--
EndColumn++
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
StringLeft, Section1, A_LoopField, StartColumn
StringMid, Section2, A_LoopField, EndColumn
OutPut .= Section1 Section2 "`n"
}
Else
OutPut .= A_LoopField "`n"
}
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_ReverseLines(Text, StartLine = 1, EndLine = 0)
{
TF_GetData(OW, Text, FileName)
StringSplit, Line, Text, `n, `r ; line0 is number of lines
If (EndLine = 0 OR EndLine = "")
EndLine:=Line0
If (EndLine > Line0)
EndLine:=Line0
CountDown:=EndLine+1
Loop, Parse, Text, `n, `r
{
If (A_Index < StartLine)
Output1 .= A_LoopField "`n" ; section1
If A_Index between %StartLine% and %Endline%
{
CountDown--
Output2 .= Line%CountDown% "`n" section2
}
If (A_Index > EndLine)
Output3 .= A_LoopField "`n"
}
OutPut.= Output1 Output2 Output3
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
;TF_SplitFileByLines
;example:
;TF_SplitFileByLines("TestFile.txt", "4", "sfile_", "txt", "1") ; split file every 3 lines
; InFile = 0 skip line e.g. do not include the actual line in any of the output files
; InFile = 1 include line IN current file
; InFile = 2 include line IN next file
TF_SplitFileByLines(Text, SplitAt, Prefix = "file", Extension = "txt", InFile = 1)
{
LineCounter=1
FileCounter=1
Where:=SplitAt
Method=1
; 1 = default, splitat every X lines,
; 2 = splitat: - rotating if applicable
; 3 = splitat: specific lines comma separated
TF_GetData(OW, Text, FileName)
IfInString, SplitAt, `- ; method 2
{
StringSplit, Split, SplitAt, `-
Part=1
Where:=Split%Part%
Method=2
}
IfInString, SplitAt, `, ; method 3
{
StringSplit, Split, SplitAt, `,
Part=1
Where:=Split%Part%
Method=3
}
Loop, Parse, Text, `n, `r
{
OutPut .= A_LoopField "`n"
If (LineCounter = Where)
{
If (InFile = 0)
{
StringReplace, CheckOutput, PreviousOutput, `n, , All
StringReplace, CheckOutput, CheckOutput, `r, , All
If (CheckOutput <> "") and (OW <> 2) ; skip empty files
TF_ReturnOutPut(1, PreviousOutput, Prefix FileCounter "." Extension, 0, 1)
If (CheckOutput <> "") and (OW = 2) ; skip empty files
TF_SetGlobal(Prefix FileCounter,PreviousOutput)
Output:=
}
If (InFile = 1)
{
StringReplace, CheckOutput, Output, `n, , All
StringReplace, CheckOutput, CheckOutput, `r, , All
If (CheckOutput <> "") and (OW <> 2) ; skip empty files
TF_ReturnOutPut(1, Output, Prefix FileCounter "." Extension, 0, 1)
If (CheckOutput <> "") and (OW = 2) ; skip empty files
TF_SetGlobal(Prefix FileCounter,Output)
Output:=
}
If (InFile = 2)
{
OutPut := PreviousOutput
StringReplace, CheckOutput, Output, `n, , All
StringReplace, CheckOutput, CheckOutput, `r, , All
If (CheckOutput <> "") and (OW <> 2) ; skip empty files
TF_ReturnOutPut(1, Output, Prefix FileCounter "." Extension, 0, 1)
If (CheckOutput <> "") and (OW = 2) ; output to array
TF_SetGlobal(Prefix FileCounter,Output)
OutPut := A_LoopField "`n"
}
If (Method <> 3)
LineCounter=0 ; reset
FileCounter++ ; next file
Part++
If (Method = 2) ; 2 = splitat: - rotating if applicable
{
If (Part > Split0)
{
Part=1
}
Where:=Split%Part%
}
If (Method = 3) ; 3 = splitat: specific lines comma separated
{
If (Part > Split0)
Where:=Split%Split0%
Else
Where:=Split%Part%
}
}
LineCounter++
PreviousOutput:=Output
PreviousLine:=A_LoopField
}
StringReplace, CheckOutput, Output, `n, , All
StringReplace, CheckOutput, CheckOutput, `r, , All
If (CheckOutPut <> "") and (OW <> 2) ; skip empty files
TF_ReturnOutPut(1, Output, Prefix FileCounter "." Extension, 0, 1)
If (CheckOutput <> "") and (OW = 2) ; output to array
{
TF_SetGlobal(Prefix FileCounter,Output)
TF_SetGlobal(Prefix . "0" , FileCounter)
}
}
; TF_SplitFileByText("TestFile.txt", "button", "sfile_", "txt") ; split file at every line with button in it, can be regexp
; InFile = 0 skip line e.g. do not include the actual line in any of the output files
; InFile = 1 include line IN current file
; InFile = 2 include line IN next file
TF_SplitFileByText(Text, SplitAt, Prefix = "file", Extension = "txt", InFile = 1)
{
LineCounter=1
FileCounter=1
TF_GetData(OW, Text, FileName)
SplitPath, TextFile,, Dir
Loop, Parse, Text, `n, `r
{
OutPut .= A_LoopField "`n"
FoundPos:=RegExMatch(A_LoopField, SplitAt)
If (FoundPos > 0)
{
If (InFile = 0)
{
StringReplace, CheckOutput, PreviousOutput, `n, , All
StringReplace, CheckOutput, CheckOutput, `r, , All
If (CheckOutput <> "") and (OW <> 2) ; skip empty files
TF_ReturnOutPut(1, PreviousOutput, Prefix FileCounter "." Extension, 0, 1)
If (CheckOutput <> "") and (OW = 2) ; output to array
TF_SetGlobal(Prefix FileCounter,PreviousOutput)
Output:=
}
If (InFile = 1)
{
StringReplace, CheckOutput, Output, `n, , All
StringReplace, CheckOutput, CheckOutput, `r, , All
If (CheckOutput <> "") and (OW <> 2) ; skip empty files
TF_ReturnOutPut(1, Output, Prefix FileCounter "." Extension, 0, 1)
If (CheckOutput <> "") and (OW = 2) ; output to array
TF_SetGlobal(Prefix FileCounter,Output)
Output:=
}
If (InFile = 2)
{
OutPut := PreviousOutput
StringReplace, CheckOutput, Output, `n, , All
StringReplace, CheckOutput, CheckOutput, `r, , All
If (CheckOutput <> "") and (OW <> 2) ; skip empty files
TF_ReturnOutPut(1, Output, Prefix FileCounter "." Extension, 0, 1)
If (CheckOutput <> "") and (OW = 2) ; output to array
TF_SetGlobal(Prefix FileCounter,Output)
OutPut := A_LoopField "`n"
}
LineCounter=0 ; reset
FileCounter++ ; next file
}
LineCounter++
PreviousOutput:=Output
PreviousLine:=A_LoopField
}
StringReplace, CheckOutput, Output, `n, , All
StringReplace, CheckOutput, CheckOutput, `r, , All
If (CheckOutPut <> "") and (OW <> 2) ; skip empty files
TF_ReturnOutPut(1, Output, Prefix FileCounter "." Extension, 0, 1)
If (CheckOutput <> "") and (OW = 2) ; output to array
{
TF_SetGlobal(Prefix FileCounter,Output)
TF_SetGlobal(Prefix . "0" , FileCounter)
}
}
TF_Find(Text, StartLine = 1, EndLine = 0, SearchText = "", ReturnFirst = 1, ReturnText = 0)
{
options:="^[imsxADJUXPS]+\)"
if RegExMatch(searchText,options,o)
searchText:=RegExReplace(searchText,options,(!InStr(o,"m") ? "m$0(*ANYCRLF)" : "$0"))
else searchText:="m)(*ANYCRLF)" searchText
options:="^[imsxADJUXPS]+\)" ; Hat tip to sinkfaze, see http://www.autohotkey.com/forum/viewtopic.php?t=60062
if RegExMatch(searchText,options,o)
searchText := RegExReplace(searchText,options,(!InStr(o,"m") ? "m$0" : "$0"))
else searchText := "m)" . searchText
TF_GetData(OW, Text, FileName)
If (RegExMatch(Text, SearchText) < 1)
Return "0" ; SearchText not in file or error, so do nothing
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
If (RegExMatch(A_LoopField, SearchText) > 0)
{
If (ReturnText = 0)
Lines .= A_Index "," ; line number
Else If (ReturnText = 1)
Lines .= A_LoopField "`n" ; text of line
Else If (ReturnText = 2)
Lines .= A_Index ": " A_LoopField "`n" ; add line number
If (ReturnFirst = 1) ; only return first occurrence
Break
}
}
}
If (Lines <> "")
StringTrimRight, Lines, Lines, 1 ; trim trailing , or `n
Else
Lines = 0 ; make sure we return 0
Return Lines
}
TF_Prepend(File1, File2)
{
FileList=
(
%File1%
%File2%
)
TF_Merge(FileList,"`n", "!" . File2)
Return
}
TF_Append(File1, File2)
{
FileList=
(
%File2%
%File1%
)
TF_Merge(FileList,"`n", "!" . File2)
Return
}
; For TF_Merge You will need to create a Filelist variable, one file per line,
; to pass on to the function:
; FileList=
; (
; c:\file1.txt
; c:\file2.txt
; )
; use Loop (files & folders) to create one quickly if you want to merge all TXT files for example
;
; Loop, c:\*.txt
; FileList .= A_LoopFileFullPath "`n"
;
; By default, a new line is used as a separator between two text files
; !merged.txt deletes target file before starting to merge files
TF_Merge(FileList, Separator = "`n", FileName = "merged.txt")
{
OW=0
Loop, Parse, FileList, `n, `r
{
Append2File= ; Just make sure it is empty
IfExist, %A_LoopField%
{
FileRead, Append2File, %A_LoopField%
If not ErrorLevel ; Successfully loaded
Output .= Append2File Separator
}
}
If (SubStr(FileName,1,1)="!") ; check if we want to delete the target file before we start
{
FileName:=SubStr(FileName,2)
OW=1
}
Return TF_ReturnOutPut(OW, OutPut, FileName, 0, 1)
}
TF_Wrap(Text, Columns = 80, AllowBreak = 0, StartLine = 1, EndLine = 0)
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
If (AllowBreak = 1)
Break=
Else
Break=[ \r?\n]
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
If (StrLen(A_LoopField) > Columns)
{
LoopField := A_LoopField " " ; just seems to work better by adding a space
OutPut .= RegExReplace(LoopField, "(.{1," . Columns . "})" . Break , "$1`n")
}
Else
OutPut .= A_LoopField "`n"
}
Else
OutPut .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_WhiteSpace(Text, RemoveLeading = 1, RemoveTrailing = 1, StartLine = 1, EndLine = 0) {
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Trim:=A_AutoTrim ; store trim settings
AutoTrim, On ; make sure AutoTrim is on
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
If (RemoveLeading = 1) AND (RemoveTrailing = 1)
{
LoopField = %A_LoopField%
Output .= LoopField "`n"
Continue
}
If (RemoveLeading = 1) AND (RemoveTrailing = 0)
{
LoopField := A_LoopField . "."
LoopField = %LoopField%
StringTrimRight, LoopField, LoopField, 1
Output .= LoopField "`n"
Continue
}
If (RemoveLeading = 0) AND (RemoveTrailing = 1)
{
LoopField := "." A_LoopField
LoopField = %LoopField%
StringTrimLeft, LoopField, LoopField, 1
Output .= LoopField "`n"
Continue
}
If (RemoveLeading = 0) AND (RemoveTrailing = 0)
{
Output .= A_LoopField "`n"
Continue
}
}
Else
Output .= A_LoopField "`n"
}
AutoTrim, %Trim% ; restore original Trim
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
; Delete lines from file1 in file2 (using StringReplace)
; Partialmatch = 2 added in 3.4
TF_Substract(File1, File2, PartialMatch = 0) {
Text:=File1
TF_GetData(OW, Text, FileName)
Str1:=Text
Text:=File2
TF_GetData(OW, Text, FileName)
OutPut:=Text
If (OW = 2)
File1= ; free mem in case of var/text
OutPut .= "`n" ; just to make sure the StringReplace will work
If (PartialMatch = 2)
{
Loop, Parse, Str1, `n, `r
{
IfInString, Output, %A_LoopField%
{
Output:= RegExReplace(Output, "im)^.*" . A_LoopField . ".*\r?\n?", replace)
}
}
}
Else If (PartialMatch = 1) ; allow paRTIal match
{
Loop, Parse, Str1, `n, `r
StringReplace, Output, Output, %A_LoopField%, , All ; remove lines from file1 in file2
}
Else If (PartialMatch = 0)
{
search:="m)^(.*)$"
replace=__bol__$1__eol__
Output:=RegExReplace(Output, search, replace)
StringReplace, Output, Output, `n__eol__,__eol__ , All ; strange fix but seems to be needed.
Loop, Parse, Str1, `n, `r
StringReplace, Output, Output, __bol__%A_LoopField%__eol__, , All ; remove lines from file1 in file2
}
If (PartialMatch = 0)
{
StringReplace, Output, Output, __bol__, , All
StringReplace, Output, Output, __eol__, , All
}
; Remove all blank lines from the text in a variable:
Loop
{
StringReplace, Output, Output, `r`n`r`n, `r`n, UseErrorLevel
if (ErrorLevel = 0) or (ErrorLevel = 1) ; No more replacements needed.
break
}
Return TF_ReturnOutPut(OW, OutPut, FileName, 0)
}
; Similar to "BK Replace EM" RangeReplace
TF_RangeReplace(Text, SearchTextBegin, SearchTextEnd, ReplaceText = "", CaseSensitive = "False", KeepBegin = 0, KeepEnd = 0)
{
TF_GetData(OW, Text, FileName)
IfNotInString, Text, %SearchText%
Return Text ; SearchTextBegin not in TextFile so return and do nothing, we have to return Text in case of a variable otherwise it would empty the variable contents bug fix 3.3
Start = 0
End = 0
If (KeepBegin = 1)
KeepBegin:=SearchTextBegin
Else
KeepBegin=
If (KeepEnd = 1)
KeepEnd:= SearchTextEnd
Else
KeepEnd=
If (SearchTextBegin = "")
Start=1
If (SearchTextEnd = "")
End=2
Loop, Parse, Text, `n, `r
{
If (End = 1) ; end has been found already, replacement made simply continue to add all lines
{
Output .= A_LoopField "`n"
Continue
}
If (Start = 0) ; start hasn't been found
{
If (InStr(A_LoopField,SearchTextBegin,CaseSensitive)) ; start has been found
{
Start = 1
KeepSection := SubStr(A_LoopField, 1, InStr(A_LoopField, SearchTextBegin)-1)
EndSection := SubStr(A_LoopField, InStr(A_LoopField, SearchTextBegin)-1)
; check if SearchEndText is in second part of line
If (InStr(EndSection,SearchTextEnd,CaseSensitive)) ; end found
{
EndSection := ReplaceText KeepEnd SubStr(EndSection, InStr(EndSection, SearchTextEnd) + StrLen(SearchTextEnd) ) "`n"
If (End <> 2)
End=1
If (End = 2)
EndSection=
}
Else
EndSection=
Output .= KeepSection KeepBegin EndSection
Continue
}
Else
Output .= A_LoopField "`n" ; if not found yet simply add
}
If (Start = 1) and (End <> 2) ; start has been found, now look for end if end isn't an empty string
{
If (InStr(A_LoopField,SearchTextEnd,CaseSensitive)) ; end found
{
End = 1
Output .= ReplaceText KeepEnd SubStr(A_LoopField, InStr(A_LoopField, SearchTextEnd) + StrLen(SearchTextEnd) ) "`n"
}
}
}
If (End = 2)
Output .= ReplaceText
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
; Create file of X lines and Y columns, fill with space or other character(s)
TF_MakeFile(Text, Lines = 1, Columns = 1, Fill = " ")
{
OW=1
If (Text = "") ; if OutPutFile is empty return as variable
OW=2
Loop, % Columns
Cols .= Fill
Loop, % Lines
Output .= Cols "`n"
Return TF_ReturnOutPut(OW, OutPut, Text, 1, 1)
}
; Convert tabs to spaces, shorthand for TF_ReplaceInLines
TF_Tab2Spaces(Text, TabStop = 4, StartLine = 1, EndLine =0)
{
Loop, % TabStop
Replace .= A_Space
Return TF_ReplaceInLines(Text, StartLine, EndLine, A_Tab, Replace)
}
; Convert spaces to tabs, shorthand for TF_ReplaceInLines
TF_Spaces2Tab(Text, TabStop = 4, StartLine = 1, EndLine =0)
{
Loop, % TabStop
Replace .= A_Space
Return TF_ReplaceInLines(Text, StartLine, EndLine, Replace, A_Tab)
}
; Sort (section of) a text file
TF_Sort(Text, SortOptions = "", StartLine = 1, EndLine = 0) ; use the SORT options http://www.autohotkey.com/docs/commands/Sort.htm
{
TF_GetData(OW, Text, FileName)
If StartLine contains -,+,`, ; no sections, incremental or multiple line input
Return
If (StartLine = 1) and (Endline = 0) ; process entire file
{
Output:=Text
Sort, Output, %SortOptions%
}
Else
{
Output := TF_ReadLines(Text, 1, StartLine-1) ; get first section
ToSort := TF_ReadLines(Text, StartLine, EndLine) ; get section to sort
Sort, ToSort, %SortOptions%
OutPut .= ToSort
OutPut .= TF_ReadLines(Text, EndLine+1) ; append last section
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
TF_Tail(Text, Lines = 1, RemoveTrailing = 0, ReturnEmpty = 1)
{
TF_GetData(OW, Text, FileName)
Neg = 0
If (Lines < 0)
{
Neg=1
Lines:= Lines * -1
}
If (ReturnEmpty = 0) ; remove blank lines first so we can't return any blank lines anyway
{
Loop, Parse, Text, `n, `r
OutPut .= (RegExMatch(A_LoopField,"[\S]+?\r?\n?")) ? A_LoopField "`n" :
StringTrimRight, OutPut, OutPut, 1 ; remove trailing `n added by loop above
Text:=OutPut
OutPut=
}
If (Neg = 1) ; get only one line!
{
Lines++
Output:=Text
StringGetPos, Pos, Output, `n, R%Lines% ; These next two Lines by Tuncay see
StringTrimLeft, Output, Output, % ++Pos ; http://www.autoHotkey.com/forum/viewtopic.php?p=262375#262375
StringGetPos, Pos, Output, `n
StringLeft, Output, Output, % Pos
Output .= "`n"
}
Else
{
Output:=Text
StringGetPos, Pos, Output, `n, R%Lines% ; These next two Lines by Tuncay see
StringTrimLeft, Output, Output, % ++Pos ; http://www.autoHotkey.com/forum/viewtopic.php?p=262375#262375
Output .= "`n"
}
OW = 2 ; make sure we return variable not process file
Return TF_ReturnOutPut(OW, OutPut, FileName, RemoveTrailing)
}
TF_Count(String, Char)
{
StringReplace, String, String, %Char%,, UseErrorLevel
Return ErrorLevel
}
TF_Save(Text, FileName, OverWrite = 1) { ; HugoV write file
Return TF_ReturnOutPut(OverWrite, Text, FileName, 0, 1)
}
TF(TextFile, CreateGlobalVar = "T") { ; read contents of file in output and %output% as global var ... http://www.autohotkey.com/forum/viewtopic.php?p=313120#313120
global
FileRead, %CreateGlobalVar%, %TextFile%
Return, (%CreateGlobalVar%)
}
; TF_Join
; SmartJoin: Detect if CHAR(s) is/are already present at the end of the line before joining the next, this to prevent unnecessary double spaces for example.
; Char: character(s) to use between new lines, defaults to a space. To use nothing use ""
TF_Join(Text, StartLine = 1, EndLine = 0, SmartJoin = 0, Char = 0)
{
If ( (InStr(StartLine,",") > 0) AND (InStr(StartLine,"-") = 0) ) OR (InStr(StartLine,"+") > 0)
Return Text ; can't do multiplelines, only multiple sections of lines e.g. "1,5" bad "1-5,15-10" good, "2+2" also bad
TF_GetData(OW, Text, FileName)
If (InStr(Text,"`n") = 0)
Return Text ; there are no lines to join so just return Text
If (InStr(StartLine,"-") > 0) ; OK, we need some counter-intuitive string mashing to substract ONE from the "endline" parameter
{
Loop, Parse, StartLine, CSV
{
StringSplit, part, A_LoopField, -
NewStartLine .= part1 "-" (part2-1) ","
}
StringTrimRight, StartLine, NewStartLine, 1
}
If (Endline > 0)
Endline--
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc)
If (Char = 0)
Char:=A_Space
Char_Org:=Char
GetRightLen:=StrLen(Char)-1
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
{
If (SmartJoin = 1)
{
GetRightText:=SubStr(A_LoopField,0)
If (GetRightText = Char)
Char=
}
Output .= A_LoopField Char
Char:=Char_Org
}
Else
Output .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}
;----- Helper functions ----------------
TF_SetGlobal(var, content = "") ; helper function for TF_Split* to return array and not files, credits Tuncay :-)
{
global
%var% := content
}
; Helper function to determine if VAR/TEXT or FILE is passed to TF
; Update 11 January 2010 (skip filecheck if `n in Text -> can't be file)
TF_GetData(byref OW, byref Text, byref FileName)
{
If (text = 0) ; v3.6
{
MsgBox, 48, TF Lib Error, % "Read Error:`npossible reason: perhaps you used ! vs ""!"" ?"
ExitApp
}
OW=0 ; default setting: asume it is a file and create file_copy
IfNotInString, Text, `n ; it can be a file as the Text doesn't contact a newline character
{
If (SubStr(Text,1,1)="!") ; first we check for "overwrite"
{
Text:=SubStr(Text,2)
OW=1 ; overwrite file (if it is a file)
}
IfNotExist, %Text% ; now we can check if the file exists, it doesn't so it is a var
{
If (OW=1) ; the variable started with a ! so we need to put it back because it is variable/text not a file
Text:= "!" . Text
OW=2 ; no file, so it is a var or Text passed on directly to TF
}
}
Else ; there is a newline character in Text so it has to be a variable
{
OW=2
}
If (OW = 0) or (OW = 1) ; it is a file, so we have to read into var Text
{
Text := (SubStr(Text,1,1)="!") ? (SubStr(Text,2)) : Text
FileName=%Text% ; Store FileName
FileRead, Text, %Text% ; Read file and return as var Text
If (ErrorLevel > 0)
{
MsgBox, 48, TF Lib Error, % "Can not read " FileName
ExitApp
}
}
Return
}
; Skan - http://www.autohotkey.com/forum/viewtopic.php?p=45880#45880
; SetWidth() : SetWidth increases a String's length by adding spaces to it and aligns it Left/Center/Right. ( Requires Space() )
TF_SetWidth(Text,Width,AlignText)
{
If (AlignText!=0 and AlignText!=1 and AlignText!=2)
AlignText=0
If AlignText=0
{
RetStr= % (Text)TF_Space(Width)
StringLeft, RetText, RetText, %Width%
}
If AlignText=1
{
Spaces:=(Width-(StrLen(Text)))
RetStr= % TF_Space(Round(Spaces/2))(Text)TF_Space(Spaces-(Round(Spaces/2)))
}
If AlignText=2
{
RetStr= % TF_Space(Width)(Text)
StringRight, RetStr, RetStr, %Width%
}
Return RetStr
}
; Skan - http://www.autohotkey.com/forum/viewtopic.php?p=45880#45880
TF_Space(Width)
{
Loop,%Width%
Space=% Space Chr(32)
Return Space
}
; Write to file or return variable depending on input
TF_ReturnOutPut(OW, Text, FileName, TrimTrailing = 1, CreateNewFile = 0) {
If (OW = 0) ; input was file, file_copy will be created, if it already exist file_copy will be overwritten
{
IfNotExist, % FileName ; check if file Exist, if not return otherwise it would create an empty file. Thanks for the idea Murp|e
{
If (CreateNewFile = 1) ; CreateNewFile used for TF_SplitFileBy* and others
{
OW = 1
Goto CreateNewFile
}
Else
Return
}
If (TrimTrailing = 1)
StringTrimRight, Text, Text, 1 ; remove trailing `n
SplitPath, FileName,, Dir, Ext, Name
If (Dir = "") ; if Dir is empty Text & script are in same directory
Dir := A_WorkingDir
IfExist, % Dir "\backup" ; if there is a backup dir, copy original file there
FileCopy, % Dir "\" Name "_copy." Ext, % Dir "\backup\" Name "_copy.bak", 1
FileDelete, % Dir "\" Name "_copy." Ext
FileAppend, %Text%, % Dir "\" Name "_copy." Ext
Return Errorlevel ? False : True
}
CreateNewFile:
If (OW = 1) ; input was file, will be overwritten by output
{
IfNotExist, % FileName ; check if file Exist, if not return otherwise it would create an empty file. Thanks for the idea Murp|e
{
If (CreateNewFile = 0) ; CreateNewFile used for TF_SplitFileBy* and others
Return
}
If (TrimTrailing = 1)
StringTrimRight, Text, Text, 1 ; remove trailing `n
SplitPath, FileName,, Dir, Ext, Name
If (Dir = "") ; if Dir is empty Text & script are in same directory
Dir := A_WorkingDir
IfExist, % Dir "\backup" ; if there is a backup dir, copy original file there
FileCopy, % Dir "\" Name "." Ext, % Dir "\backup\" Name ".bak", 1
FileDelete, % Dir "\" Name "." Ext
FileAppend, %Text%, % Dir "\" Name "." Ext
Return Errorlevel ? False : True
}
If (OW = 2) ; input was var, return variable
{
If (TrimTrailing = 1)
StringTrimRight, Text, Text, 1 ; remove trailing `n
Return Text
}
}
; _MakeMatchList()
; Purpose:
; Make a MatchList which is used in various functions
; Using a MatchList gives greater flexibility so you can process multiple
; sections of lines in one go avoiding repetitive fileread/append actions
; For TF 3.4 added COL = 0/1 option (for TF_Col* functions) and CallFunc for
; all TF_* functions to facilitate bug tracking
_MakeMatchList(Text, Start = 1, End = 0, Col = 0, CallFunc = "Not available")
{
ErrorList=
(join|
Error 01: Invalid StartLine parameter (non numerical character)`nFunction used: %CallFunc%
Error 02: Invalid EndLine parameter (non numerical character)`nFunction used: %CallFunc%
Error 03: Invalid StartLine parameter (only one + allowed)`nFunction used: %CallFunc%
)
StringSplit, ErrorMessage, ErrorList, |
Error = 0
If (Col = 1)
{
LongestLine:=TF_Stat(Text)
If (End > LongestLine) or (End = 1) ; FIXITHERE BUG
End:=LongestLine
}
TF_MatchList= ; just to be sure
If (Start = 0 or Start = "")
Start = 1
; some basic error checking
; error: only digits - and + allowed
If (RegExReplace(Start, "[ 0-9+\-\,]", "") <> "")
Error = 1
If (RegExReplace(End, "[0-9 ]", "") <> "")
Error = 2
; error: only one + allowed
If (TF_Count(Start,"+") > 1)
Error = 3
If (Error > 0 )
{
MsgBox, 48, TF Lib Error, % ErrorMessage%Error%
ExitApp
}
; Option #0 [ added 30-Oct-2010 ]
; Startline has negative value so process X last lines of file
; endline parameter ignored
If (Start < 0) ; remove last X lines from file, endline parameter ignored
{
Start:=TF_CountLines(Text) + Start + 1
End=0 ; now continue
}
; Option #1
; StartLine has + character indicating startline + incremental processing.
; EndLine will be used
; Make TF_MatchList
IfInString, Start, `+
{
If (End = 0 or End = "") ; determine number of lines
End:= TF_Count(Text, "`n") + 1
StringSplit, Section, Start, `, ; we need to create a new "TF_MatchList" so we split by ,
Loop, %Section0%
{
StringSplit, SectionLines, Section%A_Index%, `+
LoopSection:=End + 1 - SectionLines1
Counter=0
TF_MatchList .= SectionLines1 ","
Loop, %LoopSection%
{
If (A_Index >= End) ;
Break
If (Counter = (SectionLines2-1)) ; counter is smaller than the incremental value so skip
{
TF_MatchList .= (SectionLines1 + A_Index) ","
Counter=0
}
Else
Counter++
}
}
StringTrimRight, TF_MatchList, TF_MatchList, 1 ; remove trailing ,
Return TF_MatchList
}
; Option #2
; StartLine has - character indicating from-to, COULD be multiple sections.
; EndLine will be ignored
; Make TF_MatchList
IfInString, Start, `-
{
StringSplit, Section, Start, `, ; we need to create a new "TF_MatchList" so we split by ,
Loop, %Section0%
{
StringSplit, SectionLines, Section%A_Index%, `-
LoopSection:=SectionLines2 + 1 - SectionLines1
Loop, %LoopSection%
{
TF_MatchList .= (SectionLines1 - 1 + A_Index) ","
}
}
StringTrimRight, TF_MatchList, TF_MatchList, 1 ; remove trailing ,
Return TF_MatchList
}
; Option #3
; StartLine has comma indicating multiple lines.
; EndLine will be ignored
IfInString, Start, `,
{
TF_MatchList:=Start
Return TF_MatchList
}
; Option #4
; parameters passed on as StartLine, EndLine.
; Make TF_MatchList from StartLine to EndLine
If (End = 0 or End = "") ; determine number of lines
End:= TF_Count(Text, "`n") + 1
LoopTimes:=End-Start
Loop, %LoopTimes%
{
TF_MatchList .= (Start - 1 + A_Index) ","
}
TF_MatchList .= End ","
StringTrimRight, TF_MatchList, TF_MatchList, 1 ; remove trailing ,
Return TF_MatchList
}
; added for TF 3.4 col functions - currently only gets longest line may change in future
TF_Stat(Text)
{
TF_GetData(OW, Text, FileName)
Sort, Text, f _AscendingLinesL
Pos:=InStr(Text,"`n")-1
Return pos
}
_AscendingLinesL(a1, a2) ; used by TF_Stat
{
Return StrLen(a2) - StrLen(a1)
}
/* -------------- */
#include tf.ahk
msg =
(
123
456
789
000000
)
TF_RemoveLines(msg, 1,3)
MsgBox % msg
MsgBox % RegExReplace(msg, "^[^\n]+\n[^\n]+\n[^\n]+\n...", "")
mozers, спасибо! Но если сместить четвертую строку на пятую, оставив четвертую пустой, то удаление символов переходит на пятую строку.
becauseim, правильно формулируй условие (включая все возможные варианты).
RegExReplace(msg, "^.*(...)$", "$1")
Так - тупо 3 последних символа. Хотя так можно и вообще без регулярки. Что надо?
mozers, последние три не нужно, нужно убрать именно с начала четвертой строки и только три символа. Сейчас же остаются три символа с конца текста.
Также хотелось бы иметь возможность изменить сценарий таким образом, чтобы удалялись не три, а четыре строки с начала текста, а также, например, пять, а не три символов с восьмой, а не четвертой строки.
При абсолютном отсутствии понимания таких выражений, мне было бы лучше, наверное, использовать упомянутую выше библиотеку с фнкциями, но и с ней у меня возникли сложности.
Этот ваш, извините за прямоту, набор слов я понял так: "Удалить все начальные строки и 3 первых символа последней строки".
MsgBox % RegExReplace(msg, "^([^\n]+\n)+...", "")
Не так? Формулируйте четко.
mozers, переход строки может быть и \r и \n\r.
Malcev, неправда Ваша - \r\n А редчайший случай с \r - да - не ловит. Но у нас же винда а не никсы...
mozers, теперь результат тот же, что и в первом Вашем примере. Символы съедаются на пятой строке.
И по-прежнему, не понимаю, как изменить данное выражение под другие значения.
Имеется в виду конткретная строка, в данном случае, четвертая. Т.е. при таком исходном тексте MsgBox должен содержать все имеющиеся в тексте нули, т.к. четвертая строка пуста:
msg =
(
123
456
789
000000
)
Если с помощью регулярных выражений нельзя обозначать порядковый номер строки для редактирования, так и скажите, т.к. я не знаю.
mozers
Вообще-то есть \R. Но не суть. Задача не решена. Написано, что нужно удалить n-ое число начальных строк + 3 первые символа у n-ой строки. Т.е. промежуточные строки (в т.ч. пустые) должны остаться.
Malcev, неправда Ваша - \r\n
Официально да. Но может же в принципе быть и \n\r:
msgbox Malcev`n`rнеправда Ваша - \r\n
Уже двое пытаются изложить ТЗ. Убейте меня - я не понимаю что надо.
RegExReplace(msg, "^([^\n]*?\n){3}...", "")
Так? Если - нет - я сдаюсь - телепатия кончилась.
mozers
Проще проигнорировать, если конкретика неясна. Лично я всё понял.
becauseim, если RegEx не нужен (и тут я абсолютно с вами согласен), тогда зачем постить в эту тему?
Сами нарываетесь на решения, в которые не врубитесь.
Напишите в тему TF, или заведите новую.
msg =
(
123
456
789
000000
)
msgbox % RegexReplace(msg, "(.*?\R){3}([^\r\n]{0,3})\R?")