Issue with Handling Multiline Text and String Matching

Posted by Gabil on Thu 22 Aug 2024 11:47 AM — 5 posts, 9,318 views.

#0
This target list table that I created

<triggers>
  <trigger
   enabled="y"
   ignore_case="y"
   match="^\(Party\): You say, &quot;Target Order: (.*)&quot;$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>-- Declare target_list globally
target_list = {}

-- Debugging output to check the captured line
local line = GetLineInfo(GetLinesInBufferCount(), 1)
Note("Captured line: " .. line)

-- Match and clean up the target order
local targets_line = string.match(line, 'Target Order:%s*(.+)')
if targets_line then
    Note("Matched targets line: " .. targets_line)
    
    -- Process each target in the line
    for target in string.gmatch(targets_line, "([^,]+)") do
        target = target:gsub("^%s+", ""):gsub("%s+$", ""):gsub("[^%w%s]", "")  -- Trim and clean target
        Note("Found target: " .. target)
        table.insert(target_list, target)
    end
    
    -- Check if the target list was populated
    if #target_list &gt; 0 then
        for i, target in ipairs(target_list) do
            Note("Target " .. i .. ": " .. target)
        end
    else
        Note("Target list is empty.")
    end
else
    Note("No match found for target order.")
end</send>
  </trigger>
</triggers>


This is the trigger that tries to match the values in the target list table with the line but is unsuccessful:

<triggers>
  <trigger
   enabled="y"
   group="Multi Line"
   ignore_case="y"
   lines_to_match="2"
   match="^You see the following people here:\n(.+)$"
   multi_line="y"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>

-- Capture the line listing people in the room
local line = GetLineInfo(GetLinesInBufferCount(), 1)
Note("Captured line: " .. line)

-- Match and extract the people in the room
local names_line = string.match(line, "You see the following people here:%s*(.*)")
if names_line then
    Note("Matched names line: " .. names_line)
    
    -- Iterate through the target_list and check if any target is in names_line
    for _, target in ipairs(target_list) do
        -- Use pattern matching to check if the target name exists in the names_line
        if string.find(names_line, "%f[%a]" .. target .. "%f[%A]") then
            Send("PT Target: " .. target)
            Note("Target found and command sent: " .. target)
            break -- Stop after the first match
        end
    end
else
    Note("No names found in the line.")
end</send>
  </trigger>
</triggers>


I'm relatively new for such things. I've worked on this a lot, but it hasn't worked. Is there something I missed or a mistake I've made?
Australia Forum Administrator #1
Please copy and paste some example text that you are trying to match on.
#2
Hello Nick,

Thanks for the answer. The first script is triggered when I send the eg target order below:

(Party): You say, "Target Order: Mike, Stevie, Tesha, Gabi, Dega, Indica, Rose, Rosette, Rosiette, Akri."


This creates a table that contains all the targets.

I want to use this target list when I send the 'who here' command. It should match the first target according to the list and then send it to the party. The multiline should be something like this:

You see the following people here:
Stevie, Gabi, Mike, Rosiette, Akri



I am unable to match the values in the target_list table with the names in the second line.
Amended on Fri 23 Aug 2024 02:43 PM by Gabil
Australia Forum Administrator #3
The problem was with how you were capturing the matched line.

Using "local line = GetLineInfo(GetLinesInBufferCount(), 1)" was unnecessarily complex and also only returned the last line.

I changed it to:


local line = "%0"


... in your first trigger, and in the second one, because there would be embedded linefeeds:


local line = [=[%0]=]


The amended triggers are:


<triggers>
  <trigger
   enabled="y"
   ignore_case="y"
   match="^\(Party\): You say, &quot;Target Order: (.*)&quot;$"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>-- Declare target_list globally
target_list = {}

local line = "%0"
Note("Captured line: " .. line)

-- Match and clean up the target order
local targets_line = string.match(line, 'Target Order:%s*(.+)')
if targets_line then
    Note("Matched targets line: " .. targets_line)
    
    -- Process each target in the line
    for target in string.gmatch(targets_line, "([^,]+)") do
        target = target:gsub("^%s+", ""):gsub("%s+$", ""):gsub("[^%w%s]", "")  -- Trim and clean target
        Note("Found target: '" .. target .. "'")
        table.insert(target_list, target)
    end
    
    -- Check if the target list was populated
    if #target_list &gt; 0 then
        for i, target in ipairs(target_list) do
            Note("Target " .. i .. ": " .. target)
        end
    else
        Note("Target list is empty.")
    end
else
    Note("No match found for target order.")
end</send>
  </trigger>
  <trigger
   enabled="y"
   group="Multi Line"
   ignore_case="y"
   lines_to_match="2"
   match="^You see the following people here:\n(.+)$"
   multi_line="y"
   regexp="y"
   send_to="12"
   sequence="100"
  >
  <send>

-- Capture the line listing people in the room
local line = [=[%0]=]
Note("Captured line: " .. line)

-- Match and extract the people in the room
local names_line = string.match(line, "You see the following people here:%s*(.*)")
if names_line then
    Note("Matched names line: " .. names_line)
    
    -- Iterate through the target_list and check if any target is in names_line
    for _, target in ipairs(target_list) do
        -- Use pattern matching to check if the target name exists in the names_line
        if string.find(names_line, "%f[%a]" .. target .. "%f[%A]") then
            Send("PT Target: " .. target)
            Note("Target found and command sent: " .. target)
            break -- Stop after the first match
        end
    end
else
    Note("No names found in the line.")
end</send>
  </trigger>
</triggers>


Template:pasting
For advice on how to copy the above, and paste it into MUSHclient, please see Pasting XML.





Then using your test data it seems to work OK:


(Party): You say, "Target Order: Mike, Stevie, Tesha, Gabi, Dega, Indica, Rose, Rosette, Rosiette, Akri."
Captured line: (Party): You say, "Target Order: Mike, Stevie, Tesha, Gabi, Dega, Indica, Rose, Rosette, Rosiette, Akri."
Matched targets line: Mike, Stevie, Tesha, Gabi, Dega, Indica, Rose, Rosette, Rosiette, Akri."
Found target: 'Mike'
Found target: 'Stevie'
Found target: 'Tesha'
Found target: 'Gabi'
Found target: 'Dega'
Found target: 'Indica'
Found target: 'Rose'
Found target: 'Rosette'
Found target: 'Rosiette'
Found target: 'Akri'
Target 1: Mike
Target 2: Stevie
Target 3: Tesha
Target 4: Gabi
Target 5: Dega
Target 6: Indica
Target 7: Rose
Target 8: Rosette
Target 9: Rosiette
Target 10: Akri

You see the following people here:
Stevie, Gabi, Mike, Rosiette, Akri
Captured line: You see the following people here:
Stevie, Gabi, Mike, Rosiette, Akri
Matched names line: Stevie, Gabi, Mike, Rosiette, Akri
Target found and command sent: Mike
#4
Thank you very much, Nick!