Parsing text file - Lua - lua

I have a text file contains:
<Response>
<IP>17.178.96.59</IP>
<CountryCode>US</CountryCode>
<CountryName>United States</CountryName>
<RegionCode></RegionCode>
<RegionName></RegionName>
<City>Chicago</City>
<ZipCode></ZipCode>
<TimeZone>America/Chicago</TimeZone>
<Latitude>37.751</Latitude>
<Longitude>-97.822</Longitude>
<MetroCode>0</MetroCode>
</Response>
How to remove each and so I get only:
17.178.96.59,
US,
United States,
nil,
nil,
Chicago,
nil,
America/Chicago,
37.751,
-97.822,
0
Using the Lua script.

You don't show what you already tried, but there is a recently discussed SO question on how to iterate over XML nodes that should work well for your purposes. Just replace fixed element names with something like [%w_]+ and collect parsed values into a table and you'll get the result you are looking for.

This is what I am trying to do.
int = getInternet()
url3 = 'https://freegeoip.app/xml/17.178.96.59'
result = int.getURL(url3)
result = result:gsub("><",">nil<"):gsub("<.->",""):gsub("%c%s+",","):sub(2)..'nil'
print(result)
-- = 17.178.96.59,US,United States,nil,nil,nil,nil,America/Chicago,37.751,-97.822,0,mil
geoResult = {}
for word in string.gmatch(result, '([^,]+)') do
--print(word)
table.insert(geoResult, word)
--for i,v in ipairs(result) do print(i,v) end
end
print('IP : '..geoResult[1])
print('Country ID : '..geoResult[2])
print('Country Name : '..geoResult[3])
print('Region Code : '..geoResult[4])
print('Region Name : '..geoResult[5])
print('City : '..geoResult[8])
print('ZIP Code : '..geoResult[7])
print('Time Zone : '..geoResult[8])
print('Latitude : '..geoResult[9])
print('Longitude : '..geoResult[10])
print('Metro Code : '..geoResult[11])
-- result:
17.178.96.59,US,United States,nil,nil,nil,nil,America/Chicago,37.751,-97.822,0,nil
IP : 17.178.96.59
Country ID : US
Country Name : United States
Region Code : nil
Region Name : nil
City : America/Chicago
ZIP Code : nil
Time Zone : America/Chicago
Latitude : 37.751
Longitude : -97.822
Metro Code : 0

Related

Form data is not correct with Suave web server

I am trying to receive a confirmation from AWS' SNS system.
It sends a message through a POST to a webserver and I'm receiving it using Suave.
When I get the message, the form field is truncated, I am receiving:
"{\n \"Type\" : \"SubscriptionConfirmation\",\n \"MessageId\" : \"13dd68fa-2720-419a-8d8a-edc9f4466ea3\",\n \"Token\" : \"2336412f37fb687f5d51e6e2425e90ccf23f36200405c1942ea85f0874b382c47327c4bfd63203eace5240bb7b253428af362a04a61c8f98ab1718c679e9e27594529615adf5d86729374cce472768b91622851aced957c1dcddf21e3d82b48f5ff528c8dbc911179a3f26126a8d7f00\",\n \"TopicArn\" : \"arn:aws:sns:ap-northeast-1:960544703730:igorbot\",\n \"Message\" : \"You have chosen to subscribe to the topic arn:aws:sns:ap-northeast-1:960544703730:igorbot.\\nTo confirm the subscription, visit the SubscribeURL included in this message.\",\n \"SubscribeURL\" : \"https://sns.ap-northeast-1.amazonaws.com/?Action",
"ConfirmSubscription"
so it's an unfinished json...
but when I look at the rawForm field, I get the whole message:
{
"Type" : "SubscriptionConfirmation",
"MessageId" : "0645c009-f4fa-4fb7-9c94-127e98f5eb76",
"Token" : "2336412f37fb687f5d51e6e2425e90ccf23f36200406641a9f63b753dad1d31c61da2ebeea8cdaeed2e3c04f701bd08e2d2c9cac65676979e43c1089a96779f9b57a0e0f072013333db51472ca43c1e6a0854cf3af6769d95c7911d74c9e2bec22db93de90e537d480070891ddaaa548",
"TopicArn" : "arn:aws:sns:ap-northeast-1:960544703730:igorbot",
"Message" : "You have chosen to subscribe to the topic arn:aws:sns:ap-northeast-1:960544703730:igorbot.\nTo confirm the subscription, visit the SubscribeURL included in this message.",
"SubscribeURL" : "https://sns.ap-northeast-1.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:ap-northeast-1:960544703730:igorbot&Token=2336412f37fb687f5d51e6e2425e90ccf23f36200406641a9f63b753dad1d31c61da2ebeea8cdaeed2e3c04f701bd08e2d2c9cac65676979e43c1089a96779f9b57a0e0f072013333db51472ca43c1e6a0854cf3af6769d95c7911d74c9e2bec22db93de90e537d480070891ddaaa548",
"Timestamp" : "2021-03-13T20:36:21.918Z",
"SignatureVersion" : "1",
"Signature" : "FBnpuGtkZmzox+5ryo1/4k1hgwmoeuvcptQ2dOyyneShVHovmdemMqo9JFTzbBFelTN7FMojX/sIjFs2dZoQYeqEgsQW9WqCiEstDQu0toHn7KKxapzIoGfjfh6Rikfy8Liv88RRNLC2DLtxWW2JWr5Mmwkjtro/pm7vyJhfp5G4qcAB3gtBOtVm+XOAai6rY7obcMojkmMr4jDd9UqutV6imyYDCH+PvUCnc7aKg6p4EmZO33VlRibIPa5PiN1Sj/mmNhyoeR4pGu+0Jci+utvonXaYPgtlDuEyoVcgUQ6lki1xiclIRpDm4FvOL5tvUSq+Jdjz3prlNDNM8AuQpQ==",
"SigningCertURL" : "https://sns.ap-northeast-1.amazonaws.com/SimpleNotificationService-010a507c1833636cd94bdb98bd93083a.pem"
}
At first I thought the output was truncated, but then I narrowed it down. Posting this line:
{
"SubscribeURL" : "https://sns.ap-northeast-1.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:ap-northeast-1:960544703730:igorbot&Token=2336412f37fb687f5d51e6e2425e90ccf23f36200406641a9f63b753dad1d31c61da2ebeea8cdaeed2e3c04f701bd08e2d2c9cac65676979e43c1089a96779f9b57a0e0f072013333db51472ca43c1e6a0854cf3af6769d95c7911d74c9e2bec22db93de90e537d480070891ddaaa548"
}
will fail and get truncated at the first '=' sign. Then:
{
"SubscribeURL" : "abc=3"
}
will cause Suave to fail. When sent as form data, it will not be converted to a string properly.
Is there any setting related to encoding, etc that would allow to prevent this? (since I can't ask AWS to escape all their '=' signs)
JSON and form data (application/x-www-form-urlencoded, to be specific) have different syntax. Form data looks like key1=value1&key2=value2, so Suave is breaking the string on & and = in order to parse it.
You can parse JSON using mapJson instead. Something like this should work:
open System.Runtime.Serialization
open Suave
open Suave.Json
[<DataContract>]
type Subscription =
{
[<field: DataMember(Name = "SubscribeURL")>]
SubscribeUrl : string;
}
[<EntryPoint>]
let main argv =
let app = mapJson (fun sub -> sprintf "URL: %s" sub.SubscribeUrl)
startWebServer defaultConfig app
0

Using a single pattern to capture multiple values containing in a file in lua script

i have a text file that contains data in the format YEAR, CITY, COUNTRY. data is written as one YEAR, CITY, COUNTRY per line. eg -:
1896, Athens, Greece
1900, Paris, France
Previously i was using the data hard coded like this
local data = {}
data[1] = { year = 1896, city = "Athens", country = "Greece" }
data[2] = { year = 1900, city = "Paris", country = "France" }
data[3] = { year = 1904, city = "St Louis", country = "USA" }
data[4] = { year = 1908, city = "London", country = "UK" }
data[5] = { year = 1912, city = "Stockholm", country = "Sweden" }
data[6] = { year = 1920, city = "Antwerp", country = "Netherlands" }
Now i need to read the lines from the file and get the values in to the private knowledge base "local data = {} "
Cant figure out how to capture multiple values using a single pattern from the data in the file.
My code so far is
local path = system.pathForFile( "olympicData.txt", system.ResourceDirectory )
-- Open the file handle
local file, errorString = io.open( path, "r" )
if not file then
-- Error occurred; output the cause
print( "File error: " .. errorString )
else
-- Read each line of the file
for line in file:lines() do
local i, value = line:match("%d")
table.insert(data, i)
-- Close the file
io.close(file)
end
file = nil
Given that you read a line like
1896, Athens, Greece
You can simply obtain the desired values using captures.
https://www.lua.org/manual/5.3/manual.html#6.4.1
Captures: A pattern can contain sub-patterns enclosed in parentheses; they describe captures. When a match succeeds, the
substrings of the subject string that match captures are stored
(captured) for future use. Captures are numbered according to their
left parentheses. For instance, in the pattern "(a*(.)%w(%s*))", the
part of the string matching "a*(.)%w(%s*)" is stored as the first
capture (and therefore has number 1); the character matching "." is
captured with number 2, and the part matching "%s*" has number 3.
As a special case, the empty capture () captures the current string
position (a number). For instance, if we apply the pattern "()aa()" on
the string "flaaap", there will be two captures: 3 and 5.
local example = "1896, Athens, Greece"
local year, city, country = example:match("(%d+), (%w+), (%w+)")
print(year, city, country)

Lua get Instance in an instance where the name matches a string

I am a javascript developer and am starting to use lua.
When i write code such as:
var obj = {
prop: "Hello World"
}
, propName = "prop";
//and to fetch the value:
console.log(obj[propName]);
/as apposed to:
console.log(obj.propName) //undefined
in lua is there any way to get a property of an Instance that has the same name as a string.
--i.e:
game.Workspace.<INSERT VARIABLE VALUE HERE>.Humanoid.WalkSpeed = 100
P.S i am using lua for roblox if that makes any changes
I don't known roblox but try this:
game.Workspace[myvar].Humanoid.WalkSpeed = 100
In this sense, Lua is like JavaScript.

Text file reading with dict in python

From bellow text file, read the text file into a python program and group all the words according to their first letter. Represent the groups in form of dictionary. Where the staring alphabet is the "key" and all the words starting with the alphabets are list of "values".
Text file is:
Among other public buildings in a certain town, which for many reason it will be prudent to
refine from mentioning, and to which i will assign no fictitious name, there is one anciently
common to most towns, great or small.
stream = open('file name', 'r')
str = ''
current = ' '
while current != '':
current = stream.read(50)
str += current
words = str.split(' ')
dict = {}
for w in words:
if not w[0] in dict:
dict[w[0]] = [w]
else:
dict[w[0]].append(w)
The dictionary is dict

why is my global table being considered nil?

background:
I am trying to teach myself Lua and I am having difficulty understanding why a table is being considered nil when it has data inside it. Can anyone break it down for me why I am getting this error message from the code snippet below? It is one of my first programs and i really need to get these few concepts down before moving on to my real project. Thanks!
error message:
C:\Users\<user>\Desktop>lua luaCrap.lua
lua: luaCrap.lua:7: attempt to call global 'entry' (a nil value)
stack traceback:
luaCrap.lua:7: in main chunk
[C]: ?
code:
--this creates the function to print
function fwrite (fmt, ...)
return io.write(string.format(fmt, unpack(arg)))
end
--this is my table of strings to print
entry{
title = "test",
org = "org",
url = "http://www.google.com/",
contact = "someone",
description = [[
test1
test2
test3]]
}
--this is to print the tables first value
fwrite(entry[1])
--failed loop attempt to print table
-- for i = 1, #entry, 1 do
-- local entryPrint = entry[i] or 'Fail'
-- fwrite(entryPrint)
-- end
you are missing the assignment to entry.
you need to change the entry code to this:
entry =
{
title = "test",
org = "org",
url = "http://www.google.com/",
contact = "someone",
description = [[
test1
test2
test3]]
}
to clarify the error message, parens are assumed in certain contexts, like when you have a table directly following a label. the interpreter thinks you're trying to pass a table to a function called entry, which it can't find. it assumes you really meant this:
entry({title = "test", ...})

Resources