Log in

View Full Version : Functions to explode, implode string exist?


Rob105
28th October 2023, 14:01
Is there pre defined function in AviSynth+ similar to

explode (https://www.php.net/manual/en/function.explode.php) - Split a string by a string
and
implode (https://www.php.net/manual/en/function.implode.php) - Join array elements with a string

if not how would i make one myself, i don't know regex.

StainlessS
28th October 2023, 19:49
All builtin Avisynth string functions:- http://avisynth.nl/index.php/Internal_functions#String_functions

Also see RT_Stats:- https://forum.doom9.org/showthread.php?t=165479
Get latest RT_Stats v2.0 Beta 13 from StainlessS @ MediaFire (In sig below this post, ie):- https://www.mediafire.com/folder/hb26mthbjz7z6/StainlessS
Or Direct Link:- https://www.mediafire.com/file/xa3t1wx234gyzfq/RT_Stats_25%252626_x86_x64_dll_v2.00Beta13_20201229.zip/file

Some maybe useful Stringy thingies,

*****************************************************
****************** STRING FUNCTIONS *****************
*****************************************************

Here we use the term Txt (text) to mean a multiline string ie multiple strings separated by newline [Chr(10)].


RT_StrAddStr(String, String s1, ... , String sn)
Non-clip function.
Function to concatenate (join together) 2 or more strings.
D = RT_StrAddStr("A","B","C") same as D="A"+"B"+"C".
There is a bug in v2.58 and 2.6a3 when joining strings that result in sizes of [(n * 4096) - 1],
this function just gives an alternative method of joining strings. In v2.6a4 bug is fixed.

***
***
***

RT_StrReplace(string source,string find,string replace,bool "sig"=True) # Based on Algorithm by Vampiredom, Gavino & IanB.
String args 'source', 'find' and 'replace' unnamed and compulsory.
Takes a source string, searches for all occurences of find string and replaces the found strings with the replace string.
Can use "" in replace string (only in replace) to delete the found substrings from the source string.
Newlines are treated no differently to other characters, and could be replaced/deleted.
v1.14, added 'sig' arg,default true is Case Significant (as previous version). Set false for case insignificant find string.

***
***
***

RT_StrReplaceDeep(string source,string find,string replace,bool "sig"=True)
String args 'source', 'find' and 'replace' unnamed and compulsory.
Takes a source string, searches for all occurences of find string and replaces the found strings with the replace string.
Can use "" in replace string (only in replace) to delete the found substrings from the source string.
Newlines are treated no differently to other characters, and could be replaced/deleted.
Differs from RT_StrReplace in that will rescan after a replacement to see if the replaced string combines with currently
existing string to create another find string. Useful to replace eg " " with " ", (two spaces with 1 space), where more than
two consecutive spaces would end up with more than one consecutive resulting space if using plain RT_StrReplace.
v1.14, added 'sig' arg,default true is Case Significant (as previous version). Set false for case insignificant find string.
v2.0, Switched to using Martin53 Algorithm.

***
***
***

RT_StrReplaceMulti(string source,string find,string replace,bool "sig"=True)
String args 'source', 'find' and 'replace' unnamed and compulsory.
Takes a source string, searches for all occurences of find substrings and replaces the found substrings with the replace substrings.
Find string and Replace string are both multiline [Chr(10) separated] strings, both of n lines where find[i] and replace[i]
are matched pairs, ie the first line of a multiline find is replaced by the first line of a multiline replace, etc.
Can use "" in replace string (only in replace) to delete the found substrings from the source string.
Differs from RT_StrReplace, in that both find and replace strings are multiline strings and MUST match in number of lines.
Cannot use either carriage return [Chr(13)] or newline [Chr(10)] in find or replace as these are interpreted as end of current line,
you would need to use RT_StrReplace() instead.
eg S=RT_StrReplaceMulti("THE cat SAT.","SAT"+Chr(10)+"THE","sat"+Chr(10)+"The") produces "The cat sat.".
v1.14, added 'sig' arg,default true is Case Significant (as previous version). Set false for case insignificant find string.

***
***
***

RT_QuoteStr(string)
Non-clip function.
Encloses supplied string arg in double quotes, Use on filenames containing spaces.
Do NOT use with eg RT_FileDelete, only on filenames sent to a DOS command.

***
***
***

RT_StrPad(String,Int n,string "c"=" ")
Pads an unnamed string to at least int n (unnamed) length with first character of string c (Default SPACE).

***
***
***

RT_FindStr(String S,string Substr,bool "Sig"=True,int "Pos"=1)
Finds unnamed string Substr in unnamed string S.
Optional bool Sig: Default=True, does case significant comparison, insignificant if false.
Optional int Pos: Default=1, is start position in string S to find string Substr. If Pos smaller than 1 or greater than length of string s,
then will return 0, Not Found.
Returns position (1 relative) of found string within the FULL LENGTH string S, or 0 if not found.
Differs from Avisynth FindStr in Sig and Pos args and in that if either string S or string Substr is "" then will ALWAYS return 0, 'Not Found',
Avisynth FindStr always returns 1 if SubStr="" even if S is also "".
Care must be taken if mixing RT_FindStr and RT_TxtFindStr or RT_FileFindStr, RT_FindStr returns 0 on error, the other
two return -ve on error(0 denoting valid line zero).

***
***
***

RT_TxtAddStr(String, String s1, ... , String sn)
Non-clip function.
Function to concatenate (join together) 2 or more strings with Chr(10) line separators.
If the first string is an empty string ("") it will not have a newline [Chr(10)] appended.
All other strings even empty strings will have a newline [Chr(10)] inserted after them
(if they dont already have a trailing newline).
Any source string containing carriage return Chr(13) will have them converted to Chr(10).
X = RT_TxtAddStr("A","B","C") same as X = "A" + Chr(10) + "B" + Chr(10) +"C" + Chr(10)
X = RT_TxtAddStr("","A","B","C") same as X = "" + "A" + Chr(10) + "B" + Chr(10) + "C" + Chr(10)

***
***
***

RT_TxtQueryLines(String)
Non-clip function.
String, the multiline string that you require a line count from.
Returns the number of Newline [Chr(10)] separated lines in a multiline string.
The last line does not have to be Chr(10) terminated, it still counts.
***
***
***

RT_TxtGetLine(String, Int "Line"=0)
Non-clip function.
Extract a single line from a multiline Newline[Chr(10)] separated string. Default=0 == first line.
The Line index is Zero Relative like frame number versus FrameCount.
The returned string has trailing Newlines and carriage returns stripped from it.
Throws an error if your requested line is >= to the number of lines in the multiline string.

***
***
***

RT_TxtFindStr(String S,string FndS,bool "Sig"=True,int "Pos"=1,int "Start"=0,int "Lines"=0)
Finds unnamed string FndS in unnamed multi-line text string S, starting at line 'Start' and searching 'Lines' number of string lines.
S: is a multi-line text string, ie a newline [CHR(10)] separated list of strings.
FndS: is a single string and will be considered terminated early at the first carriage return [Chr(13)] or newline [Chr(10)],
carriage returns and newlines will not be findable using this function.
Sig: Default=True, does case significant comparison, insignificant if false.
Pos: Default=1, is the character start position in an individual line of the multi-line string S to start searching
for the FndS string. Allows you to skip search on first Pos-1 characters within all single lines of multi-line string S.
If Pos less than 1, then will return -ve number (usually -1), Not Found.
Start: Default 0, is the 0 relative starting line where the searching begins within the multi-line string S.
Lines: Default 0(all lines). Number of lines in multi-line string to seach, starting at line 'Start'.
A -ve return is 'Not Found'. On success returns the line number of the first instance of a found string in the Start and Lines
range of lines. An empty "" FndS will always return -ve result, ie Not Found (as will all errors).
see RT_TxtQueryLines, to inquire number of single lines in a chr(10) separated multi-line string.
see RT_TxtGetLine to extract a single line from a multi-line string [without trailing Chr(10) or Chr(13)].
NOTE, Character position 'Pos' is 1 relative whereas multi-line line 'Start' index is 0 relative.
Care must be taken if mixing RT_FindStr and RT_TxtFindStr or RT_FileFindStr, RT_FindStr returns 0 on error, the other
two return -ve on error(0 denoting valid line zero).

***
***
***

RT_String(String format, dat1,...,datn,int "Esc"=1)

Returns a formatted string. The unnamed 'format' string and optional unnamed 'dat' args are used to construct the text string that is
returned, uses C/CPP printf() style formatting.
Format: compulsory string controlling format and describing the datn type args that are expected.
datn: Variable number of data args of any type (excluding clip).
Esc: Default 1, converts embedded escape sequences in format string, 2 convert escape sequences in both format and datn strings,
0 no escape sequence conversion done.
It is necessary to specify the "Esc" name if you wish to alter default, as Avisynth cannot tell when the variable number of data datn
args ends.
You might wish to turn off escape conversion if you want to send a multi-line string to Subtitle() without conversion of '\n' to Chr(10).

printf Format spec here:- http://msdn.microsoft.com/en-us/library/56e442dc%28v=vs.71%29.aspx
NOTE, the only support for printing Bool variables is %s as string, ie prints "True" or "False".
Formatting supported %[flags] [width] [.precision] type
flags, one of "-,+,0, ,#"
width, integer, "*" supported (width supplied via dat arg).
Precision, integer, "*" supported (precision supplied via dat arg).
type,
"c,C,d,i,o,u,x,X", Integer type, c,C=character, d,i=signed, o,u,x,X=unsigned (o=octal, x=Hex).
"e,E,f,g,G", Floating point type
"s,S", String type (also Bool).

Formatting Insertion point is marked with '%' character in the format string (as in Avisynth String function), if you wish to use
a percent character within the returned string, it should be inserted twice in the format string ie '%%' will produce a single '%'.
The data datn arg strings do not require a double '%' character.

A Backslash character '\' introduces escape sequences, to insert a backslash character itself, you must supply a double
backslash sequence ie '\\'.
When 'Esc' is non zero, converts embedded escape character sequences (Case Significant):-
'\\' Converted to '\' Single Backslash
'\n' Converted to Chr(10) NewLine
'\r' Converted to Chr(13) Carriage Return
'\t' Converted to Chr(9) Horizontal TAB
'\v' Converted to Chr(11) Vertical TAB
'\f' Converted to Chr(12) FormFeed
'\b' Converted to Chr(8) BackSpace
'\a' Converted to Chr(7) Bell
'\x', where x is ANY OTHER CHARACTER not included above, will be copied verbatim, ie '\x'.

eg
RT_String("Hello there %s and %s.\nGoodbye %d.","Fred","Ted",2013)
would return same as:- "Hello there Fred and Ted." + Chr(10) + "Goodbye 2013."

Be aware that when 'Esc'=2, the string is constructed via two passes, the 1st pass inserts the data args into the format string,
2nd pass converts escape sequences, so the escape sequences could also exist in the datn args. Also, beware of constructing strings
which when joined together, form an escape sequence.
Take care when handling filenames with path backslash, suggest using 'Esc'=1 when data datn strings contain eg Filenames.

***
***
***

RT_TxtSort(String,int 'mode'=0)
Non-clip function.
Function to sort a Chr(10) separated multiline string.
The String arg is the multiline string, and 'mode' can be in range 0 to 11.
0 = Sort ascending, case insignificant
1 = Sort ascending, case significant
2 = Sort decending, case insignificant
3 = Sort decending, case significant
4 = Sort ascending, Filenames, digits sorted by value
5 = Sort ascending, Filenames, old style as for Windows 2000
6 = Sort decending, Filenames, digits sorted by value
7 = Sort decending, Filenames, old style as for Windows 2000
8 = Sort ascending, Integer number Strings
9 = Sort ascending, float number Strings
10= Sort decending, Integer number Strings
11= Sort decending, float number Strings

***
***
***

Some of above string functions use the term Txt (text) to mean a multiline string, where lines are Chr(10) separated.
We can use such multiline strings as a sort of pseudo array.

StainlessS
28th October 2023, 21:23
Daft demo


/*
$pizza = "piece1 piece2 piece3 piece4 piece5 piece6";
$pieces = explode(" ", $pizza);
echo $pieces[0]; // piece1
echo $pieces[1]; // piece2
*/

Pizza = "piece1 piece2 piece3 piece4"
RT_DebugF("%s",Pizza,name="PIZZA: ") # Requires DebugView from M$ :- https://learn.microsoft.com/en-us/sysinternals/downloads/debugview


Pieces = RT_StrReplace( Pizza," ",Chr(10) ) # "piece1"+Chr(10)+"piece2"+Chr(10)+"piece3"+Chr(10)+"piece4"+Chr(10)"
RT_DebugF("%s",Pieces,name="PIECES[]: ")

Puds = RT_StrReplace(Pieces,"piece","Pud") # "Pud1"+Chr(10)+"Pud2"+Chr(10)+"Pud3"+Chr(10)+"Pud4"+Chr(10)"
RT_DebugF("%s",Puds,name="PUDS[]: ")

FindS = RT_String("Pud1\nPud2") # "Pud1"+Chr(10)+"Pud2"
RT_DebugF("%s",FindS,name="FindS[]: ")

ReplaceS = RT_String("Apple\nOrange") # "Apple"+Chr(10)+"Orange"
RT_DebugF("%s",ReplaceS,name="ReplaceS[]: ")

Fruity = RT_StrReplaceMulti(Puds,FindS,ReplaceS)
RT_DebugF("%s",Fruity,name="Fruity[]: ") # "Apple"+Chr(10)+"Orange"+Chr(10)+"Pud3"+Chr(10)+"Pud4"+Chr(10)"

# Parse Pseudo array
LINES = RT_TxtQueryLines(Fruity) # Items in Multiline string (pseudo array)
RT_DebugF("Fruity has %d Lines",LINES)
for(i=0,LINES-1) {
S = RT_TxtGetLine(Fruity, Line=i) # Get line Fruity[i] string and strip any NewLine
RT_DebugF("%d] %s",i,S)
}

Juicy = RT_StrReplace(Fruity,Chr(10), " ")
RT_DebugF("%s",Juicy,name="JUICY: ") # "Apple Orange Pud3 Pud4"

return MessageClip("DONE")


Output from DebugView

00001148 21:21:16 [11604] PIZZA: piece1 piece2 piece3 piece4
00001149 21:21:16 [11604] PIECES[]: piece1
00001150 21:21:16 [11604] PIECES[]: piece2
00001151 21:21:16 [11604] PIECES[]: piece3
00001152 21:21:16 [11604] PIECES[]: piece4
00001153 21:21:16 [11604] PUDS[]: Pud1
00001154 21:21:16 [11604] PUDS[]: Pud2
00001155 21:21:16 [11604] PUDS[]: Pud3
00001156 21:21:16 [11604] PUDS[]: Pud4
00001157 21:21:16 [11604] FindS[]: Pud1
00001158 21:21:16 [11604] FindS[]: Pud2
00001159 21:21:16 [11604] ReplaceS[]: Apple
00001160 21:21:16 [11604] ReplaceS[]: Orange
00001161 21:21:16 [11604] Fruity[]: Apple
00001162 21:21:16 [11604] Fruity[]: Orange
00001163 21:21:16 [11604] Fruity[]: Pud3
00001164 21:21:16 [11604] Fruity[]: Pud4
00001165 21:21:16 [11604] RT_DebugF: Fruity has 4 Lines
00001166 21:21:16 [11604] RT_DebugF: 0] Apple
00001167 21:21:16 [11604] RT_DebugF: 1] Orange
00001168 21:21:16 [11604] RT_DebugF: 2] Pud3
00001169 21:21:16 [11604] RT_DebugF: 3] Pud4
00001170 21:21:16 [11604] JUICY: Apple Orange Pud3 Pud4

StainlessS
28th October 2023, 22:17
There are a couple of libraries that might have something more akin to your reqirements (I have not looked),

Older one, AvsLib, 2007:- https://forum.doom9.org/showthread.php?p=1003478&highlight=AVSLib#post1003478

and

AviSynthLib v0.52b (2016) by Maxxon(no longer visits D9):- https://forum.doom9.org/showthread.php?t=164305
This one (IIRC) is very comprehensive.

EDIT: Also, I forgot that RT_Stats also has File Based Array and DBase, which might also be of use.
(Very large [GigaByte] Arrays and DBases)

And these two funcs,

RT_DBaseReadCSV(String DB, String CSV, String "Separator"=",",String "StrDelimiter"="\"",Int "StartField"=0,Int "EndField"=last_field)

This function will extract CSV values in text file, and append them as records to an appropriately formatted DBase file.

DB, FileName of an RT_Stats DBase file.
CSV, FileName of a text CSV (Comma Separated Value) file.
Separator Default "," ie comma separator (first character only, Chr()'s 0, 13, 10, and 34 [Double Quote] illegal).
Default Separator "," (Comma) is optional and so long as CSV values are SPACE/TAB separated will not produce an error
if separator is missing.
StrDelimiter Default = "\"" ie single character string Double Quote.
StrDelimiter (String Delimiter) can be multiple characters (empty string "" illegal, also cannot contain the Separator
character nor SPACE or TAB), Default is a Double Quote single character string.
CSV string values CANNOT contain StrDelimiter string, ie for default StrDelimiter, strings cannot contain a double
quote character string. So long as the StrDelimiter does not appear within any string, nearly any StrDelimiter can be
used, eg "@@@" is a 3 character StrDelimiter that you could use in place of double quote string delimiters, where the
string values could then contain a double quote character, in such a case you should enclosed CSV strings as in
@@@Some text that contains a " double quote.@@@.
NOTE, StrDelimiter IS case sensitive, so if using alphabetic characters they have to match exactly.

StartField Default = 0.
EndField Default = last field in DBase record (By default, all fields should be present in CSV file, else error).
Above StartField and EndField args allow setting of limited number of CONSECUTIVE fields within a record, the remaining
fields if any are set to NULL values, ie String all zero chars, bool = false, Float=0.0, int and bin=0.

Function returns Int, the number of records added to the DBase.
(Maximum line length in CSV text file is 64*1024 characters).

Example:-
CSV.txt file containing text something like this
###
1 ,42.0 ,true , "Hello" # I am a comment
2 ,43.5 ,false, "Goodbye"
$FF,3.142,TRUE , "Coconuts" # So Am I
###
Script:-
DB = "My.DB"
CSV = "CSV.txt"
RT_DBaseAlloc(DB,0,"ifbs32") # Allocate DBase with 0 pre-allocated records, 4 fields, 0)=Int, 1)=Float, 2)=bool, 3=String(maxlen=32).
Added=RT_DBaseReadCSV(DB,CSV)
Return MessageClip("Added "+String(Added)+" Records") # Shows "Added 3 Records".


***
***
***


RT_DBaseWriteCSV(String DB, String CSV, String "Separator"=",",String "StrDelimiter"="\"",Int "StartField"=0,Int "EndField"=last_field
Int "Low"=0,Int "High"=Last_Record,Bool "Append"=False,String "Fmt"="")

This function will write a consecutinve number of fields from a DBase to CSV values in text file, for each DBase record between
records low and high inclusive.

DB, FileName of an RT_Stats DBase file.
CSV, FileName of an output text CSV (Comma Separated Value) file.
Separator Default "," ie comma separator (first character only, Chr()'s 0, 13, 10, and 34 [Double Quote] illegal).
Default Separator "," (Comma).

StrDelimiter Default = "\"" ie single character string Double Quote. String delimiters written around string fields when written to CSV.
StrDelimiter (String Delimiter) can be multiple characters (empty string "" illegal, also cannot contain the Separator
character nor SPACE or TAB), Default is a Double Quote single character string.
DBase string values CANNOT contain StrDelimiter string, ie for default StrDelimiter, strings cannot contain a double quote
character string. So long as the StrDelimiter does not appear within any DB string, nearly any StrDelimiter can be
used, eg "@@@" is a 3 character StrDelimiter that you could use in place of double quote string delimiters, where the
string values could then contain a double quote character, in such a case you could enclose CSV strings as in
@@@Some text that contains a " double quote.@@@.
NOTE, StrDelimiter IS case sensitive, so if using alphabetic characters they have to match exactly.

StartField Default = 0.
EndField Default = last field in DBase record (By default, all fields are written to CSV file).
Above StartField and EndField args allow writing of limited number of CONSECUTIVE fields within a record.

Append Default False. When True, append if CSV file already exists.

Fmt Default, "". The Fmt string provides a little bit of optional formatting for field types Int, Bin and Bool.
The length of Fmt string can be up to EndField-StartField+1, ie 1 character for each of the selected fields.
A single character can be set for each of the fields, first one affects StartField, and the last one affects
EndField (assuming all characters are set). A shorter Fmt string only affects those fields for the characters that
exist in the Fmt string.
A SPACE (' ') or '.' Fmt character uses default formatting behaviour (Proper Case for Bool, ie 1st charcter is upper
case, remainder are lower case).
Type Int, If ' ' or '.' then default eg "-1".
If 'x' then print fields as lower case Hex eg ffffffff.
If 'X' then print fields as upper case Hex eg FFFFFFFF.
If '$' then print fields as upper case Hex preceded by a '$' Dollar character eg eg $FFFFFFFF.
Type Bool. If ' ' or '.' then default eg "True".
if 'l' or 'L' then lower case eg 'true'.
if 'u' or 'U' then upper case eg 'TRUE'.
Type Bin, If ' ' or '.' then default eg "255".
If 'x' then print fields as lower case Hex eg ff.
If 'X' then print fields as upper case Hex eg FF.
If '$' then print fields as upper case Hex preceded by a '$' Dollar character eg eg $FF.
Types String, Float (or internal use type Double) will error if using anything other than '.' or ' '.


Function returns Int, the number of records added to the CSV file.

Example:-
CSVTXT="""
1,42.5,$FF,true, "D:\OUT\Test_000001.d2v" # Comment
2,43.5,$FE,false,"D:\OUT\Test_000002.d2v"
3,44.5,$FD,true, "D:\OUT\Test_000003.d2v"
4,45.5,$FC,false,"D:\OUT\Test_000004.d2v"
-1,45.5,$FC,false,"D:\OUT\Test_000004.d2v"
"""

DB = "My.DB"
CSVIN = "CSVIN.txt"
CSVOUT = "CSVOUT.txt" # Output CSV file.
RT_WriteFile(CSVIN,"%s",CSVTXT) # Create test Input CSV
RT_DBaseAlloc(DB,0,"ifnbs512") # Allocate DBase with 0 pre-allocated records, 5 fields, Int, Float, Bin, Bool and String[512].
Read=RT_DBaseReadCSV(DB,CSVIN)
Written=RT_DBaseWriteCSV(DB,CSVOUT,Append=false,Fmt="$.x..")
S=RT_String("Read = %d written=%d",read,Written) # Shows "Read=5 Written=5".
MessageClip(S)

EDIT:
RT_DBaseAlloc(DB,0,"ifnbs512") # Allocate DBase with 0 pre-allocated records, 5 fields, Int, Float, Bin, Bool and String[512].

In above DBase examples, a Field of type 'Bin', is an unsigned 8 bit integer.

Rob105
29th October 2023, 13:46
Oh my god such a simple question, such a complicated answer :)


I like short on the point answers not into doing research and trying something in the middle of developing a script.

Here i made my own explode function, works good for me.

function explode(string delimiter, string myString)
{

myString = TrimAll(myString)

myArr = []

while(StrLen(myString) > 0)
{
pos = FindStr(myString, delimiter)

if(pos > 0)
{
myArr = ArrayAdd(myArr, TrimAll(MidStr(myString, 1, pos)))
myString = TrimAll(MidStr(myString, pos, StrLen(myString)))
#replaces all occurances myString = TrimAll(ReplaceStr(myString, MidStr(myString, 1, pos), ""))
} else {
myArr = ArrayAdd(myArr, TrimAll(myString))
myString = ""
}
}

return myArr

}

StainlessS
29th October 2023, 14:10
Good, you found your own answer.
I aint figured out how any of that new fangled avs+ array stuff works yet. :(
All the other stuff also works with avs prior to avs+.

EDIT:
When you do similar for the Implode() script function, post here so as of use to others.
Tanks.