Split string into text and integers

Thanks to the many RS232 posts here, I got our weigh scale correctly connected to a Pi via an RS232-USB cable, and got the output to flow into the Pi upon using the inject node. Only thing that remains is splitting the output so that I have the integer value (which will range from 0 to about 1999). Obviously a split node (yet none of my choices are working), and maybe followed by a function node to turn it into an integer.

Hello .. in order for people to test this and recommend some way to split the string
we'll need a sample of the msg.payload.

In the Debug window Hover your mouse over one of the msgs and copy a value
image

Paste in the forum with the Preformatted Text tool
image

you can use a regEx in a function node to filter out the digits from the string

Test flow :

[{"id":"8806650f1c55dc18","type":"function","z":"4895ea10b4ee9ead","name":"","func":"let match = msg.payload.match(/([\\d]+)/)\nif (match && match.length > 1) {\n    msg.payload = Number(match[1])\n    return msg;\n}","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":1160,"wires":[["8d55388d3ea272c8"]]},{"id":"97e7ba1cb2fd319a","type":"inject","z":"4895ea10b4ee9ead","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"SGWGross  1233 lb","payloadType":"str","x":330,"y":1160,"wires":[["8806650f1c55dc18"]]},{"id":"8d55388d3ea272c8","type":"debug","z":"4895ea10b4ee9ead","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":730,"y":1160,"wires":[]}]

Sorry about that. Here's a sample of msg.payload

SGWGross    1248 lb

Your flow solved it! I do not know much about Regex expressions, so will study yours now to see how it works. Many thanks!

Regular expressions are just a fancy way to do some filtering
its is defined between slashes /<regEx>/

In our case /(\d+)/ translates to ...
\d any digit (number)
+ any 1 or more
[] defines a character set .. not really needed in our search (you can remove it)
the () defines a group. Which we used in our code match[1] to select this group

ps. im new to these also .. i had to look most of it up on the net :wink:

If you don’t understand or want to learn regEx, you could probably do it with a change node using the replace options to get rid of the lbs and SGWgross.

If one used the change node as you described, and removed the SGWgross and lbs (leaving just the number), would it still be considered a string, and thus require some change node to make it an integer? (I would try this but the flow is on my work PC).

You're right it would still be a string which is easily converted. To handle a variable number of spaces, here is a change node example using JSONata:


rule 1 changes multiple spaces to one space
rule 2 splits the string into an array of three items (no spaces)
rule 3 grabs the second item in the array (the string characters of the number)
rule 4 converts it to a number
Here is the flow and with will handle decimal points in the number too

[{"id":"f8c2cb8c3cabfcba","type":"inject","z":"62c97fa4b68932fd","name":"SGWGross        1214  lb","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"SGWGross        1214  lb","payloadType":"str","x":310,"y":400,"wires":[["7263cf675a67d8d0","6d73fcef9ec1972d"]]},{"id":"1e7b99b2768829d2","type":"debug","z":"62c97fa4b68932fd","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":930,"y":400,"wires":[]},{"id":"7263cf675a67d8d0","type":"change","z":"62c97fa4b68932fd","name":"change with 4 JSONata expressions","rules":[{"t":"set","p":"payload","pt":"msg","to":"$trim(payload)","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"$split(payload,' ' )","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"payload[1]\t","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"$number(payload)\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":670,"y":400,"wires":[["1e7b99b2768829d2"]]},{"id":"6d73fcef9ec1972d","type":"change","z":"62c97fa4b68932fd","name":"all four JSONata expressions in one","rules":[{"t":"set","p":"payload","pt":"msg","to":"$number($split($trim(payload),' ' )[1])\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":670,"y":460,"wires":[["f5f5e29369843f72"]]},{"id":"f5f5e29369843f72","type":"debug","z":"62c97fa4b68932fd","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":930,"y":460,"wires":[]},{"id":"4c01b2334f2ce504","type":"inject","z":"62c97fa4b68932fd","name":"SGWGross        121.4  lb","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"SGWGross        121.4  lb","payloadType":"str","x":310,"y":480,"wires":[["6d73fcef9ec1972d","7263cf675a67d8d0"]]}]
2 Likes

I, too, love to use regex in cases like this -- and generally I try to keep as much information as possible, in case I need it downstream...

Many implementations of regex (Java, JS, etc) allow you to not only find matching groups of characters, but to "tag" them with meaningful names as well. So in a function node, you can use this code to split up the incoming string:

let info = payload.match(/(?<name>\w+)\s+(?<value>\d+)\s+(?<units>\w+)?/);
let data = info && info.groups || {}; // if the string matched, return the groups object
if (data.value && typeof data.value === 'string') {
    data.value = +data.value; // coerce the value to a number
}
msg.payload = data;

to output a msg object that looks like this:

{
    "name": "SGWGross",
    "value": 1248,
    "units": "lb"
}

Sadly, it seems that JSONata's $match function does not yet support this capture group tagging... I tried ;*)

1 Like

Try

$match($$.payload,/(\w+)\s+(\d+)\s+(\w*)\s/)
[edit] should read more carefully, i see you meant named groups [end]

but i would just split it.

$split($$.payload,/\s+/,3)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.