Revome over gsub()

Hi!
I have nested field as :

  "statement" => {
          "cntxt" => {
            "extension" => {
                "https://ssss/xp/w/yy" => "xxxxxxx"
            }
        },
 ...
}

the field "extension" is dynamic. I want to remove "https://ssss/xp/" to get

  "statement" => {
          "cntxt" => {
            "extension" => {
                "w/yy" => "xxxxxxx"
            }
        },
 ...
}

After fiew review in this discuss forum I tried with

ruby {
    code => "
      hash = event.to_hash
      hash.each do |k,v|
       if k.start_with?'https://ssss/xp/'
        event.set(k.gsub('https://ssss/xp/',''), v)
       end
      end
    "
  }
}

But it's not work.

Thanks for your help !

That just iterates over the top level entries in the hash. If you need to recursively descend into hashes or arrays then you need something more like this.

Ok,

I tried to adapt your code like below

ruby {
        code => '
            def removePartStings(object, name, event)
                if object
                    if object.kind_of?(Hash) and object != {}
                        object.each { |k, v| removePartStings(v, "#{name}[#{k}]", event) }
                    elsif object.kind_of?(Array) and object != []
                        object.each_index { |i|
                            removePartStings(object[i], "#{name}[#{i}]", event)
                        }
                    else
                        lastElement = name.gsub(/^.*\[/, "").gsub(/\]$/, "")
						if lastElement.start_with?("https://ssss/xp/")
							event.set(lastElement.gsub("https://ssss/xp/)","_"), event.remove(name))
                        end
                    end
                end
            end

            event.to_hash.each { |k, v|
                removePartStings(v, "[#{k}]", event)
            }
        '
    }

I know that is not correct (it not works) but I do can't do better. Any correction will help. Thanks

event.set(lastElement.gsub("https://ssss/xp/)","_"), event.remove(name))`
                                            ^

Remove that parenthesis and you will get a top level field

     "_w/yy" => "xxxxxxx",

Also, I recently learned that defining the function in the code option is a big performance hit. Do it in the init option...

    ruby {
        init => '
            def removePartStings(object, name, event)
                if object
                    if object.kind_of?(Hash) and object != {}
                        object.each { |k, v| removePartStings(v, "#{name}[#{k}]", event) }
                    elsif object.kind_of?(Array) and object != []
                        object.each_index { |i|
                            removePartStings(object[i], "#{name}[#{i}]", event)
                        }
                    else
                        lastElement = name.gsub(/^.*\[/, "").gsub(/\]$/, "")
                        if lastElement.start_with?("https://ssss/xp/")
                            event.set(lastElement.gsub("https://ssss/xp/","_"), event.remove(name))
                        end
                    end
                end
            end
        '
        code => '
            event.to_hash.each { |k, v|
                removePartStings(v, "[#{k}]", event)
            }
        '
    }

Thank you!!! It works

Last question about it.

Where to modify if we want to apply it (the recusive function) to values (not keys) using another starting string word (say not "https://ssss/xp/" but "xt") or if any, apply simultaneously two conditional changes with a same function?

I tried to add changes to do that but no effect as result.

Thank a lot!!!