Extract \n from a string to build an array

I'm sure I'm making some obvious mistake, but wanted to check here before I start writing code in a function block.

I have a string with \n characters with in it.
I have that set as the payload, and figured I could have a split node split the payload on every \n, so I could get a payload array made each time \n was pressed.

I feel like I'm missing something obvious since that's what the node defaults to.

but even when I pass in the string: test\ntesting\ntested
that remains one string in the payload, rather than 3 messages.

running on Windows 10 if that makes a difference.

What do I need to do to Split a long string based on \n and format each split into an array?

[
    {
        "id": "39125df2bacaf839",
        "type": "debug",
        "z": "60c7ee1b0aa52cb1",
        "name": "debug 11",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1760,
        "y": 700,
        "wires": []
    },
    {
        "id": "f2a2b5cbc288472a",
        "type": "split",
        "z": "60c7ee1b0aa52cb1",
        "name": "",
        "splt": "\"\\n\"",
        "spltType": "str",
        "arraySplt": 1,
        "arraySpltType": "len",
        "stream": false,
        "addname": "",
        "x": 1610,
        "y": 700,
        "wires": [
            [
                "39125df2bacaf839"
            ]
        ]
    },
    {
        "id": "3df7822c7506fec0",
        "type": "inject",
        "z": "60c7ee1b0aa52cb1",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "test\\ntesting\\ntested",
        "payloadType": "str",
        "x": 1490,
        "y": 660,
        "wires": [
            [
                "f2a2b5cbc288472a"
            ]
        ]
    }
]

EDIT: I know how to do this with a function block using Javascript .split("\n"), I was just curious why the split node doesn't seem to be working as intended. I'm assuming it has something to do with the need for multiple \ Characters in Javascript.

Hi.

Sorry I am not going to give you an answer.

But a suggestion:
Your message has these \n characters in it that are delimiters.

Why not use a split node before you get to the function node?

Split the message into ... payload2.

Then when the message arrives at/in the function node: rather than parsing the msg.payload, you have an array of msg.payload2 already built.

Just a thought. (And I know that is dangerous for me to do too much.) :wink:

(Ok, it maybe replaces what is in msg.payload.... But it is an idea.)

The sample Code I posted only has an Inject with the payload string "test\ntesting\ntested", a Split node, and a Debug.

I was hoping running that sample would give me 3 msgs in debug window, with payloads, "test" "testing""tested" So I could use a Join Node into an array for the payload.

I'm not sure what you mean by splitting the string into payload2

Hang on.

I'll see what I can make.

Ok, (sorry no answer at this stage):
That is a test message you are sending. Fair enough.
But I suspect it is not correctly constructed.
\n is a .... token for <enter> It isn't as simple as putting \n between text and it will be translated to being <enter>. So what you have won't help you in the longer term I fear.

Can you post a REAL message you want to split?

Just to show you what I am understanding.

This is an example of what I was wanting to suggest you do. Sorry I forgot to include the join node.

But this gets what you want to do done. Just not with your message.

[{"id":"bb832d4dd25a6295","type":"join","z":"0918ee609bf69fc7","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":4360,"y":1770,"wires":[["80bba3edf1ea5572"]]},{"id":"6dbca91562963511","type":"split","z":"0918ee609bf69fc7","name":"","splt":" ","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":4210,"y":1770,"wires":[["1c91f6c03fb33f31","bb832d4dd25a6295"]]},{"id":"80bba3edf1ea5572","type":"debug","z":"0918ee609bf69fc7","name":"debug 65","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":4500,"y":1770,"wires":[]},{"id":"cd8f97e65093af34","type":"inject","z":"0918ee609bf69fc7","name":"Test","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"a b c d e f g h","payloadType":"str","x":4060,"y":1770,"wires":[["6dbca91562963511"]]},{"id":"1c91f6c03fb33f31","type":"debug","z":"0918ee609bf69fc7","name":"debug 64","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":4370,"y":1730,"wires":[]}]

I was using that test message, because that's how the string arrives.

I'm building a robot that will parse an incoming email.

The Test Email sends the email body as payload, and it arrives with \n in between words. So I need this type of Test String to parse into an array. I don't have the option to really do it another way, since my end users will be typing a response in the email body, so my options on how to parse it are limited, hence why i wanted to use \n

What's weird is I edited my post to say, I can do this easily with a function node using Javascript .split function.

I was able to make a separate array by using .split on the payload.

So at this point I'm just trying to learn for myself why the Split node doesn't do it, but the Javascript Split function does.

Maybe because ...

I can't say. Sorry.

But searching for \n in text file, I read this:
https://stackoverflow.com/questions/7063567/writing-a-n-in-a-text-file

reply # 18. (At the top)

It is "\\n"

The split node you posted also had "\n" which I also think is wrong.

You should only need the \n part or \\n.

But that is way above me.

Why can't you use the spaces between the words?
(Just saying/asking.)

The Goal is I have a form of questions that I want them to reply to.

So Instead of parsing every single word, I want to parse each mention of \n

That way I can search for the question I supply, and if one of the payload array members matches the question, I know what the rest of that string in the array is the answer to my question.

If the user hits Enter to add another sentence, that will show up as the next element in the array.

But because their response does not match my next question, I'll know that the next payload string from the array is still part of the last question.

So once I've searched the entire array for where each of my questions is, I'll know all the elements in the payload array that correspond to the question I sent.

For example if I say:
"How did that make you feel?\n"
I can search the payload array for that phrase, and it will return an index, telling me where the question was. Let's say, [3]

The next question then is:
"What do you think we should do?:\n"
The result of searching the payload array then returns a match at element [6]

Now I know that payload index 4 and 5 are related to the question at index 3, and index 6 is the next question.

I'm making a mini form out of the email body, because I need to be able to customize what the Client sees, but the answers will need to be recorded in a specific way. Which is the only reason I don't use a form. People are used to emails, and it's nice for them to have a direct message that they can track.

Ok.

Sorry then. I can't help. I haven't played enough with this sort of thing to really be able to help.

Didn't mean to get your hopes up. I was just trying to offer an alternative.

I hope someone else can help you as I am sure it isn't that hard. It is just I don't know how to do it.

What does the real data look like, show us.

The inject node set to string will not allow \n to represent a newline.
you can do so in a json or use a template.
e.g.

[{"id":"3df7822c7506fec0","type":"inject","z":"da8a6ef0b3c9a5c8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"test\\ntesting\\ntested","payloadType":"str","x":240,"y":3940,"wires":[["1c91f6c03fb33f31"]]},{"id":"1c91f6c03fb33f31","type":"debug","z":"da8a6ef0b3c9a5c8","name":"debug 64","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":560,"y":4040,"wires":[]},{"id":"9a352d8a05cd1071","type":"template","z":"da8a6ef0b3c9a5c8","name":"test string","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"test\ntesting\ntested","output":"str","x":360,"y":4060,"wires":[["1c91f6c03fb33f31"]]},{"id":"f6a9a77e2fbff0bc","type":"inject","z":"da8a6ef0b3c9a5c8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"\"test\\ntesting\\ntested\"","payloadType":"json","x":220,"y":4000,"wires":[["1c91f6c03fb33f31"]]},{"id":"b6199eedcf921b39","type":"inject","z":"da8a6ef0b3c9a5c8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":180,"y":4060,"wires":[["9a352d8a05cd1071"]]}]
1 Like

I am on my phone so can't look at your flow, but reading the comments I deduce that in your test string you have a backlash followed by n. That is two characters and is not the same as a single return key character, which is often shown as \n.
If you feed a real message into a debug node you will see the difference. I am not sure how to include newline chars in an inject node, I expect someone will tell us. Alternatively, in a function node use

msg.payload = "a\nseries\nof\nwords"
return msg
1 Like

Not wanting to steal @Colin's thunder:

This works for what you want/posted.

[{"id":"3df7822c7506fec0","type":"inject","z":"0918ee609bf69fc7","name":"Test","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"foo","payloadType":"str","x":4000,"y":1650,"wires":[["9293ac693de1b9f9"]]},{"id":"9293ac693de1b9f9","type":"function","z":"0918ee609bf69fc7","name":"function 14","func":"msg.payload = \"test\\ntesting\\ntested\";\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":4130,"y":1590,"wires":[["f2a2b5cbc288472a"]]},{"id":"f2a2b5cbc288472a","type":"split","z":"0918ee609bf69fc7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":4230,"y":1650,"wires":[["39125df2bacaf839","bb832d4dd25a6295"]]},{"id":"bb832d4dd25a6295","type":"join","z":"0918ee609bf69fc7","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":4360,"y":1770,"wires":[["80bba3edf1ea5572"]]},{"id":"80bba3edf1ea5572","type":"debug","z":"0918ee609bf69fc7","name":"debug 65","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":4500,"y":1770,"wires":[]}]

But as it was pointed out:
You have to use a function node to create the message.

Not quite true, check my example.

1 Like

Oh sorry @E1cid I did see you also helped.

I put together a flow and it did seem to do what I think is wanted.

If you set the input node to send json (rather than a string) - and add quotes - then it will send the \n as required - eg

[{"id":"6e524ff7893aa157","type":"inject","z":"d9819a729b397b63","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"\"test\\ntesting\\ntested\"","payloadType":"json","x":385,"y":150,"wires":[["4f4714e9f762c5b3"]]}]

Okay sorry I missed your reply earlier.

Why am I doing this?

Here's the idea, you have a QR code sticker you left on a piece of equipment your company built. A user scans it, and it opens an email that's pre filled out.

The email is addressed to support@company.com, and a Subject designed to forward the email to the appropriate team, in this case a node red parser.

The body of the email has some contact info for phone calls, but also has some basic questions for reporting a fault with the system and to document when the fault occurred.

The basic format of the Email body will encourage the user to enter their answer below the question.

Then they are free to press enter as many times as they want while they organize their response to the question.

A d since I ready know what question I already put in the email, I can tell what blocks of texts between the questions I know I ask are responses, and what strings are mine.

How does thay work?

I just showed showed you.

Don't believe me? Go all and look at that last paragraph.

Everything between my first question of "Why am I doing this?" And "How does it work; is my answer to the first question. So if I had a long string of text, say from an email filled out with how something faulted, I could split that text based on New Lines.

By searching that array for text that matched a question I asked, it would then know that all the things from index 1 (since index 0 is the end of the introduction and first question, to index 14, which is the next entry in the array that matches a known question

You could consider it like using the email message as a form itself for the user to fill out.

So the resulting email thay arrives in support@company.com inbox is monitored by node red,

And this email message of one long string, delimited by \n is the best way of making the email form flexible enough for them to communicate in a way that they can organically organize their thoughts, And my system can be flexible enough to include all data flexibly.

Hi @dceejay, Your suggestion definitely works but could you explain how/why?

It seems like some sort of weird voodoo - sending a string but pretending it's JSON. Does it work like that by design or is it an unintended artifact that someone noticed and found useful?

chris

A potential issue is that \n will only be the correct line ending for non-Windows mail users and possibly not for Apple users either. You would also need to deal with multiple line breaks and what if the users mail client only sends you the HTML version and not the text version. Even where they send both, are you picking out the correct version from the encoded email?

Also, what happens if someone changes the text of one of your questions? How does that impact things?

It is valid JSON: https://codebeautify.org/jsonvalidator/y23225b3a

1 Like