/*----------------------------------+ Library for Text File Manipulation | ------------------------------------+ - heresy Last Updated : 2008-06-18 -# Common Parameters ----------------------------------------------------------- TextFile : The Filename including path to read from and save to If TextFile starts with ! (eg: "!c:\sample.txt") will overwrite the text file else will save to copy of the text file (eg:Filename_copy.txt) Text : Used with functinos which supports text insertion Line : Used with functions which supports One-line process StartLine : Used with functions which supports Range of lines EndLine: Used with functions which supports Range of lines SearchText : Used with functions which supports Replacement ReplaceText : Used with functions which supports Replacement -------------------------------------------------------------------------------- -# Functions ------------------------------------------------------------------- ----------------+ Basic Functions | ----------------+ - TXT_TotalLines(TextFile) Get total lines of text file - TXT_ReadLines(TextFile, StartLine, EndLine) Read range of lines from text file (Extended version of FileReadLine) - TXT_Tail(TextFile, Lines = 1) by HugoV Get tail(last line) of text file --------------------+ Alignment Functions | --------------------+ - TXT_AlignLeft(TextFile, Columns=80) - TXT_AlignCenter(TextFile, Columns=80) - TXT_AlignRight(TextFile, Columns=80) Align texts Left/Center/Right based on total columns. Note that leading white spaces will be stripped out - TXT_ReverseLines(TextFile, StartLine = 0, EndLine = 0) by HugoV Realign range of lines with reverse order Omit 2nd and 3rd parameters to affect on every lines ---------------------+ Removement Functions | ---------------------+ - TXT_RemoveLines(TextFile, StartLine, EndLine) Remove range of lines in text file - TXT_RemoveBlankLines(TextFile) Simply removes all blank lines in text file - TXT_RemoveDuplicateLines(TextFile, CaseSensitive="True") Remove duplicated lines in text file, Case Sensitive by default ----------------------+ Replacement Functions | ----------------------+ - TXT_Replace(TextFile, SearchText, ReplaceText="") Replace Every %SearchText% to %ReplaceText% in text file to replace with "", omit 3rd Parameter(ReplaceText) - TXT_RegExReplace(TextFile, StartLine, EndLine, NeedleRegEx, Replacement="") Replace range of lines with Regular Expression to replace with "", omit Last parameter(Replacement) - TXT_ReplaceLine(TextFile, Line, Text="") Simliar to InsertLine except it will replace the line instead of inserting to replace with "", omit 3rd Parameter(Text) --------------------+ Insertion Functions | --------------------+ - TXT_LineNumber(TextFile, LeadingZeros = 0) by HugoV Insert Line Number on every line in text file with LeadingZero or not. - TXT_InsertLine(TextFile, Line, Text) Insert specified %Text% at specified %Line% - TXT_InsertPrefix(TextFile, StartLine, EndLine, Text) Insert %Text% at beforehand on range of lines - TXT_InsertSuffix(TextFile, StartLine, EndLine, Text) Insert %Text% at afterward on range of lines -----------------+ Column Functions | -----------------+ - TXT_ColGet(TextFile, StartColumn, EndColumn, Skip = 0) by HugoV Get texts between %StartColumn% and %EndColumn% and save. Empty lines can be ignored (Skip=0) or not - TXT_ColPut(TextFile, StartColumn, Text, Skip = 0) by HugoV Put %Text% at specified %StartColumn% and save. - TXT_ColCut(TextFile, StartColumn, EndColumn) by HugoV Cut texts between %StartColumn% and %EndColumn% and save. -------------------+ Trimming Functions | -------------------+ - TXT_TrimLeft(TextFile, StartLine, EndLine, Count) TXT_TrimRight(TextFile, StartLine, EndLine, Count) Trim left or right for range of lines (Work same as StringTrimLeft/Right) --------------+ CSV Functions | --------------+ - TXT_GetCSV(TextFile, Row, Column, Delimiter=",") Get field data from specific Row & Column also Delimiter can be changed. (eg: A_Space or A_Tab without ") - TXT_SetCSV(TextFile, Row, Column, Text="", Delimiter=",") Set field data at specific Row & Column also Delimiter can be changed. (eg: A_Space or A_Tab without ") --------------------------+ File Join/Split Functions | --------------------------+ - TXT_ConCat(FirstTextFile, SecondTextFile, OutputFile, Blanks = 0, FirstPadMargin = 0, SecondPadMargin = 0) by HugoV Concatenate %FirstTextFile% and %SecondTextFile% and save to %OutputFile% Optionally can set specific blank, margin rules. -------------------------------------------------------------------------------- */ ;Borrowed from SKAN. Thanks! ;http://www.autohotkey.com/forum/viewtopic.php?t=26146#162899 TXT_TotalLines(TextFile){ Original := A_BatchLines SetBatchLines, -1 FileRead, Str, %TextFile% StringReplace, Str, Str, `n, `n, UseErrorLevel SetBatchLines, %Original% Return ErrorLevel+1 } TXT_ReadLines(TextFile, StartLine, EndLine){ Original := A_BatchLines SetBatchLines, -1 FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If A_Index between %StartLine% and %Endline% OutPut .= A_LoopField "`n" Else if (A_Index=EndLine+1) Break } SetBatchLines, %Original% Return OutPut } TXT_Replace(TextFile, SearchText, ReplaceText=""){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% StringReplace, Output, Str, %SearchText%, %ReplaceText%, All If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_RegExReplace(TextFile, StartLine, EndLine, NeedleRegEx, Replacement=""){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If A_Index between %StartLine% and %Endline% { OutPut .= RegExReplace(A_LoopField, NeedleRegEx, Replacement, Count) OutPut .= "`n" Counts += Count } Else OutPut .= A_LoopField "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% Return Counts } TXT_RemoveLines(TextFile, StartLine, EndLine){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If A_Index between %StartLine% and %Endline% Continue Else OutPut .= A_LoopField "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_RemoveBlankLines(TextFile){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `r`n OutPut .= (RegExMatch(A_LoopField,"[\S]+?")) ? A_LoopField "`n" : If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_RemoveDuplicateLines(TextFile, CaseSensitive="True"){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Case := (CaseSensitive="True") ? "C" : Sort, Str, U %Case% Removed := Errorlevel If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% Return Removed } TXT_InsertLine(TextFile, Line, Text){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If A_Index < %Line% Head .= A_LoopField "`n" Else If A_Index >= %Line% Tail .= A_LoopField "`n" } OutPut := Head . Text "`n" . Tail If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_ReplaceLine(TextFile, Line, ReplaceText=""){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r OutPut .= (A_Index=Line) ? ReplaceText "`n" : A_LoopField "`n" If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_InsertPrefix(TextFile, StartLine, EndLine, Text){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If A_Index between %StartLine% and %Endline% OutPut .= Text A_LoopField "`n" Else OutPut .= A_LoopField "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_InsertSuffix(TextFile, StartLine, EndLine, Text){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If A_Index between %StartLine% and %Endline% OutPut .= A_LoopField Text "`n" Else OutPut .= A_LoopField "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_TrimLeft(TextFile, StartLine, EndLine, Count){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If A_Index between %StartLine% and %Endline% { StringTrimLeft, StrOutPut, A_LoopField, %Count% OutPut .= StrOutPut "`n" } } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_TrimRight(TextFile, StartLine, EndLine, Count){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If A_Index between %StartLine% and %Endline% { StringTrimRight, StrOutPut, A_LoopField, %Count% OutPut .= StrOutPut "`n" } } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_AlignLeft(TextFile, Columns=80){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { LoopField := RegExReplace(A_LoopField,"(^\s+)") SpaceNum := Columns-StrLen(LoopField)-1 OutPut .= LoopField "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_AlignCenter(TextFile, Columns=80){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { LoopField := RegExReplace(A_LoopField,"^\s+") SpaceNum := (Columns-StrLen(LoopField)-1)/2 VarSetCapacity(Spaces%A_Index%, SpaceNum, 32) If (StrLen(LoopField) >= Columns) OutPut .= LoopFIeld "`n" Else OutPut .= Spaces%A_Index% LoopField "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_AlignRight(TextFile, Columns=80){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { LoopField := RegExReplace(A_LoopField,"^\s+") SpaceNum := Columns-StrLen(LoopField)-1 VarSetCapacity(Spaces%A_Index%, SpaceNum, 32) If (StrLen(LoopField) >= Columns) OutPut .= LoopFIeld "`n" Else OutPut .= Spaces%A_Index% LoopField "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_GetCSV(TextFile, Row=1, Column=1, Delimiter=","){ ;A_Tab, A_Space Original := A_BatchLines SetBatchLines, -1 FileReadLine, Str, %TextFile%, %Row% StringSplit, Line, Str, %Delimiter% Output := Line%Column% SetBatchLines, %Original% Return Output } ; How SetCSV Works : ; 1) Get all lines into memory ; 2) If processing line doesn't match to specified Row, Don't touch it ; 3) Else Split row by delimiter ; 4) If A_Index matches to specified column set it with specified text ; 5) add delimiter or not based on column position (last=don't add) TXT_SetCSV(TextFile, Row, Column, Text="", Delimiter=","){ ;A_Tab, A_Space Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If (A_Index!=Row) OutPut .= A_LoopField "`n" Else { StringSplit, Line, A_LoopField, %Delimiter% Loop, %Line0% { if (A_Index!=Column) Output .= Line%A_Index% Delimiter Else OutPut .= (Line0!=Column) ? Text Delimiter : Text } OutPut .= "`n" } } If OW { FileDelete, %TextFile% If ErrorLevel Return ErrorLevel FileAppend, %OutPut%, %TextFile% If ErrorLevel Return ErrorLevel } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext If ErrorLevel Return ErrorLevel FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext If ErrorLevel Return ErrorLevel } SetBatchLines, %Original% } ; __________________________________________________________ /* / Functions below this are contributed by other people. / Thanks for their efforts and contribution ! / ______________________________________________________/ */ ;____________________ ; Functions by HugoV \________________________________________________ ; http://www.autohotkey.com/forum/profile.php?mode=viewprofile&u=5470 | ;____________________________________________________________________/ /* Based on: CONCATenate text files, ftp://garbo.uwasa.fi/pc/ts/tsfltc22.zip Usage: TXT_ConCat(FirstTextFile, SecondTextFile, OutputFile, Blanks = 0, FirstPadMargin = 0, SecondPadMargin = 0) With TXT_ConCat you can join Text files side by side. Blanks is number of blanks between lines You can pad with blanks the right margin of either of the text files, for this use FirstPadMargin and SecondPadMargin Example: TXT_ConCat("file1.txt","file2.txt","concat.txt","15","5","7") -> 15 spaces between the lines from file1 and file1, padding first file 5 spaces, padding Send file 7 Improvement: perhaps introduce a character which can be used instead of the spaces */ TXT_ConCat(FirstTextFile, SecondTextFile, OutputFile, Blanks = 0, FirstPadMargin = 0, SecondPadMargin = 0){ Original := A_BatchLines SetBatchLines, -1 If (Blanks > 0) Loop, %Blanks% InsertBlanks .= A_Space If (FirstPadMargin > 0) Loop, %FirstPadMargin% PaddingFile1 .= A_Space If (SecondPadMargin > 0) Loop, %SecondPadMargin% PaddingFile2 .= A_Space ; first we need to determin the file with the most lines for our loop File1:=TXT_TotalLines(FirstTextFile) File2:=TXT_TotalLines(SecondTextFile) If (File1 > File2) MaxLoop:=File1 Else MaxLoop:=File2 Loop, %MaxLoop% { FileReadLine, Section1, %FirstTextFile%, %A_Index% FileReadLine, Section2, %SecondTextFile%, %A_Index% OutPut .= Section1 PaddingFile1 InsertBlanks Section2 PaddingFile2 "`n" Section1= ; otherwise it will remember the last line from the shortest file Section2= } FileAppend, %OutPut%, %OutputFile% SetBatchLines, %Original% } /* Usage: TXT_LineNumber(TextFile, LeadingZeros = 0) LeadingZeros = 0 No padding with leading zeros LeadingZeros >= 1 Include padding with leading zeros (001 v 1) */ TXT_LineNumber(TextFile, LeadingZeros = 0){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% If (LeadingZeros > 0) { StringReplace, Str, Str, `n, `n, UseErrorLevel Lines:=ErrorLevel+1 Padding:=StrLen(Lines) Loop, %Padding% PadLines .= "0" } Loop, Parse, Str, `n { LineNumber:= A_Index If (LeadingZeros > 0) { LineNumber := Padlines LineNumber ; add padding StringRight, LineNumber, LineNumber, StrLen(Lines) ; remove excess padding } OutPut .= LineNumber A_Space A_LoopField "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_ColGet(TextFile, StartColumn, EndColumn, Skip = 0){ ;skip = empty lines Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile EndColumn:=(EndColumn+1)-StartColumn FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { If (Skip = 1) and (A_LoopField ="") Continue StringMid, Section, A_LoopField, StartColumn,EndColumn OutPut .= Section "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } /* Based on: COLPUT.EXE & CUT.EXE, ftp://garbo.uwasa.fi/pc/ts/tsfltc22.zip */ TXT_ColPut(TextFile, StartColumn, Text, Skip = 0){ ; skip = shorter lines (e.g. lines shorter startcolumn position) Original := A_BatchLines SetBatchLines, -1 StartColumn-- FileRead, Str, %TextFile% TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile Loop, Parse, Str, `n, `r { StringLeft, Section1, A_LoopField, StartColumn StringMid, Section2, A_LoopField, StartColumn If (Skip = 1) and (StrLen(A_LoopField) < StartColumn) OutPut .= Section1 Section2 "`n" Else OutPut .= Section1 Text Section2 "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_ColCut(TextFile, StartColumn, EndColumn){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile StartColumn-- EndColumn++ FileRead, Str, %TextFile% Loop, Parse, Str, `n, `r { StringLeft, Section1, A_LoopField, StartColumn StringMid, Section2, A_LoopField, EndColumn OutPut .= Section1 Section2 "`n" } If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% } TXT_Tail(TextFile, Lines = 1) ;have dependency on TotalLines / ReadLines { Original := A_BatchLines SetBatchLines, -1 Lines-- Endline:=TXT_TotalLines(TextFile) StartLine:=EndLine - Lines OutPut:=TXT_ReadLines(TextFile, Startline, EndLine) SetBatchLines, %Original% Return Output } TXT_ReverseLines(TextFile, StartLine = 0, EndLine = 0){ Original := A_BatchLines SetBatchLines, -1 TextFile := (SubStr(TextFile,1,1)="!") ? (SubStr(TextFile,2),OW=1) : TextFile FileRead, Str, %TextFile% StringSplit, Line, Str, `n, `r If (EndLine = 0) EndLine:=Line0 If (EndLine > Line0) EndLine:=Line0 If (StartLine > 0) ; get first section { Loop, Parse, Str, `n, `r { If (A_Index < StartLine) Output1 .= A_LoopField "`n" Else Break } } CountDown:=EndLine+1 Loop, Parse, Str, `n, `r ; get reversed section { If A_Index between %StartLine% and %Endline% { CountDown-- Output2 .= Line%CountDown% "`n" } If A_Index > Endline Break } If (EndLine < Line0) ; get last section { Loop, Parse, Str, `n, `r { If (A_Index > EndLine) Output3 .= A_LoopField "`n" } } OutPut.= Output1 Output2 Output3 StringTrimRight, OutPut, OutPut, 1 ; remove trailing `n If OW { FileDelete, %TextFile% FileAppend, %OutPut%, %TextFile% } Else { SplitPath, TextFile,, Dir, Ext, Name FileDelete, % Dir "\" Name "_copy." Ext FileAppend, %OutPut%, % Dir "\" Name "_copy." Ext } SetBatchLines, %Original% }