I would like to define a HereString then work with it line by line. Initially I figured the lines would be innate in the HereString, so I could foreach ($line in $hereString)
, and when that didn't work I tried Get-Content $hereString
. No joy in either case.
The goal is just to work on a bit of code that will eventually manipulate entire text files, so I could quickly convert to using a small example text file while implementing this, but now I am curious if HereStrings even CAN be worked with line by line, without splitting somehow.

- 6,257
- 6
- 36
- 89
-
2*without splitting somehow* `[Regex]::Matches($hereString, '^.*?(?=\r?$)','Multiline').Value`. But, IMHO, `$hereString -split '\r?\n'` is much easer. Is there a reason, why you do not want to split string? – user4003407 Jan 21 '17 at 11:23
-
Not so much that I don't want to, as I figured that there would be an easier way, and I was a little surprised when nothing (simple) seemed to work. Given that ultimately I will be working with separate files, making my little test stub also load a file is a non issue, so that's what I will do. Would be nice if you could just iterate through the individual lines a herestring with no extra processing though. – Gordon Jan 21 '17 at 11:39
-
1I'm yet to see a popular language that allows line-by-line iteration through a string (not an array of strings) without explicitly specifying that it should be split or otherwise processed (e.g. regex and so on). – wOxxOm Jan 21 '17 at 11:50
4 Answers
Your could do this:
foreach ( $line in $herestring.replace("`r`n", "`n").split("`n") ) {
'>>>{0}<<<' -f $line;
}
The replace() being there to replace Windows' CRLF line terminator with just a new line...

- 2,141
- 1
- 13
- 15
As PetSerAl suggests, the simplest solution is probably using the -split
operator:
foreach($line in $herestring -split '\r?\n')
{
# process $line here
}
using the pattern \r?\n
will match both \r\n
(Windows-style newline) and \n
(Unix-style newline)

- 1
- 1

- 157,619
- 12
- 148
- 206
Since your intent is to use this to process files, I'd start with something like this:
$file = 'c:\testfiles\testfile1.txt'
$textdata =
@'
Line1
Line2
Line3
'@
$textdata | Set-Content $file
$lines = Get-Content $file
foreach ($line in $lines) {}
Now you're testing in the same environment that you'll be working with in production, and you can experiment with different I/O methods as well as different data parsing and manipulation methods. Knowing how to do this will become more important from a performance standpoint as the size and number of files involved scales upwards.

- 66,130
- 7
- 114
- 135
-
Ha! Of course, make a herestring, then push it out to the temporary txt file and start working with it. Delete the herestring and the push, and change the path, and it's working with live data. Nice. – Gordon Jan 21 '17 at 14:01
note that both 'Split' and 'ForEach' cause the entire file to be parsed first before processing begins. if the file will be very large, there will be a delay before processing starts and memory can become a concern.
another alternative comes from .NET in the form of a textreader...
$rdr = new-object System.IO.StreamReader('c:\path\to\file.txt')
while (!$rdr.EndOfStream) {
$line = $rdr.ReadLine()
## do processing on the line ##
}
In the above, each time the ReadLine method of the StreamReader is called, it advances to the next line. The above is most efficient and gives you a chance to break out early if something is found that is not liked in the file.
You can look at the details of the StreamReader here.

- 29
- 2
-
Indeed, I was planning on Streaming for the final code. My initial plan was to test the function with an iterated herestring, then convert to a streamed file. mjolinor's approach, of using the herestring to seed the test file was perfect, because I could test different conditions without needing to jump to another editor to update the file, and it was apples to apples since the function was actually working with a file. Worked a treat. – Gordon Jan 22 '17 at 20:03