# Search for a value in an array of PSCustomObjects

**URL:** <https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358>\
**Category:** PowerShell Help\
**Created:** [June 27, 2024, 10:19am UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358 "2024-06-27T10:19:47Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![pj483](https://avatars.discourse-cdn.com/v4/letter/p/7feea3/32.png) [@pj483](https://forums.powershell.org/u/pj483)\
**Post date:** [June 27, 2024, 10:19am UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/1 "2024-06-27T10:19:47Z")

</div>

I have the following (abstract) of code:

```auto
$products = "product,description,qty`nabc123,""Product 123"",1`nxyz826,""Product 826"",0`nabc483,""Product 483"",12" | ConvertFrom-Csv -Delimiter ","
$products.GetType()
IsPublic IsSerial Name BaseType
True True Object[] System.Array
$products[0].GetType()
IsPublic IsSerial Name BaseType
True False PSCustomObject System.Object

$products
product description qty
------- ----------- ---
abc123 Product 123 1  
xyz826 Product 826 0  
abc483 Product 483 12

```

I’d like to find every string which contains a particular value (e.g. “8”) irrespective of where it is. For example:

```auto
$products | searchfor "8"
xyz826
Product 826
abc483
Product 483

```

Is there a performant way to do this? I’ve been investigating [Linq.Enumerable]::Where() but keep hitting the error “Index operation failed; the array index evaluated to null.” even when I’m just trying examples from the web.

```auto
[Linq.Enumerable]::Range(0, $products.Count).Where({param($i) $products[$i] -match "8"})
Index operation failed; the array index evaluated to null.
At line:1 char:63
+ ... Range(0, $products.Count).Where({param($i) $products[$i] -match "8"})
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex
 
Index operation failed; the array index evaluated to null.
At line:1 char:63
+ ... Range(0, $products.Count).Where({param($i) $products[$i] -match "8"})
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex
 
Index operation failed; the array index evaluated to null.
At line:1 char:63
+ ... Range(0, $products.Count).Where({param($i) $products[$i] -match "8"})
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

```

This code is just a way to demonstrate the problem I’m trying to solve which is why it’s a little odd.

Thanks.

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [June 27, 2024, 11:18am UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/2 "2024-06-27T11:18:25Z")

</div>

> [@pj483](#):
>
> I’d like to find every string which contains a particular value (e.g. “8”) irrespective of where it is.

Depending on what the actual purpose of that requirement is … how about using `Select-String` on the plain CSV text of the data?

BTW: Creating CSV reads much easier this way:

```auto
$products = 
@'
product,description,qty
abc123,"Product 123",1  
xyz826,"Product 826",0  
abc483,"Product 483",12
'@ | 
    ConvertFrom-Csv

```

---

<div class="post-metadata">

**Author:** ![pj483](https://avatars.discourse-cdn.com/v4/letter/p/7feea3/32.png) [@pj483](https://forums.powershell.org/u/pj483)\
**Post date:** [June 27, 2024, 11:56am UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/3 "2024-06-27T11:56:05Z")

</div>

Hi. Thanks or the formatting suggestion. I just copied it from my test scenario but you’re right that it is easier to read in a forum when it is formatted sensibly 🙂

I agree with the “Select-String” suggestion but this is part of a wider problem I’m trying to solve:

- CSV file with embedded LF within the text and LF as the end of line
- Replace the embedded LF but not the end of line

Using ConvertFrom-Csv, it splits at the the end of line characters (into an object array of PSCustomObjects) but retains the embedded LF characters. If I can then track down the values (e.g. description in one row) that contain these embedded LF characters, I can escape them. Using only regex, I have to be sure that the LF character I’m finding is genuinely embedded and not an end of line.

Thanks again.

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [June 27, 2024, 12:35pm UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/4 "2024-06-27T12:35:04Z")

</div>

> [@pj483](#):
>
> Replace the embedded LF but not the end of line

How about this:

> [@Replacing LF in quoted strings](https://forums.powershell.org/t/replacing-lf-in-quoted-strings/24326/4):
>
> I did. I got this. What record? thinking So you have to set up a regex pattern to find and replace all line feed characters not followed by a double quote … man_shrugging:t3

> [@pj483](#):
>
> Using only regex, I have to be sure that the LF character I’m finding is genuinely embedded and not an end of line.

And what’s the issue with that?

**Edit:**

How many columns does your input CSV have actually?

---

<div class="post-metadata">

**Author:** ![pj483](https://avatars.discourse-cdn.com/v4/letter/p/7feea3/32.png) [@pj483](https://forums.powershell.org/u/pj483)\
**Post date:** [June 27, 2024, 12:59pm UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/5 "2024-06-27T12:59:40Z")

</div>

Hi again. Yeah I’ve been looking at a regex pattern and it’s _close_ but the ConvertFrom-Csv was handling a lot of embedded quotes in the data, etc. and I was hoping this could be a shortcut to a solution. There are 299 columns in the input file!

At the moment, my regex is:

```auto
[string]$raw = Get-Content -Path $filename -Raw
[string]$escaped = $raw -replace "([`n|])(""[^""]*)`n([^""]*"")([|`n])", '$1$2<--EOL-->$3$4' -replace "([`n|])(""[^""]*""""[^""]*)`n([^""]*"")([|`n])", '$1$2<--EOL-->$3$4'

```

which is sending me crazy 😃

---

<div class="post-metadata">

**Author:** ![pj483](https://avatars.discourse-cdn.com/v4/letter/p/7feea3/32.png) [@pj483](https://forums.powershell.org/u/pj483)\
**Post date:** [June 27, 2024, 1:15pm UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/6 "2024-06-27T13:15:57Z")

</div>

For those who don’t speak regex fluently:

**1st “-replace”**

 ![First -replace](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/2X/a/aa9af7074763f75ba915b86197e680612760e88e.png)  
with the result being:

> 1st Captured Group  
> 2nd Captured Group  
> \<–EOL–\>  
> 3rd Captured Group  
> 4th Captured Group

**2nd “-replace”** (to handle escaped double-quotes _within_ a value)

 ![Second -replace](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/2X/2/2fd65eb46a92248306a48b1323149df4cfa7af82.png)  
with the result being:

> 1st Captured Group  
> 2nd Captured Group  
> \<–EOL–\>  
> 3rd Captured Group  
> 4th Captured Group

---

<div class="post-metadata">

**Author:** ![Olaf](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/olaf/32/992_2.png) [@Olaf](https://forums.powershell.org/u/Olaf)\
**Post date:** [June 27, 2024, 1:27pm UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/7 "2024-06-27T13:27:40Z")

</div>

> [@pj483](#):
>
> At the moment, my regex is:

Hmm … does it have to be that complex? Depending on how your input data really look like and if every single cell is wrapped in double quotes I’d start with a simple negative lookahead. I mentioned that before. I’d look for a line break character NOT followed by a double quote.

```auto
[string]$raw = Get-Content -Path $filename -Raw
[string]$escaped = $raw -replace '`n(?!")'

```

… I’m not sure if the double quotes needs to be escaped … in this case you could try …

```auto
[string]$raw = Get-Content -Path $filename -Raw
[string]$escaped = $raw -replace '`n(?!\")'

```

---

<div class="post-metadata">

**Author:** ![pj483](https://avatars.discourse-cdn.com/v4/letter/p/7feea3/32.png) [@pj483](https://forums.powershell.org/u/pj483)\
**Post date:** [June 27, 2024, 1:54pm UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/8 "2024-06-27T13:54:04Z")

</div>

The script is going to be processing differently-formatted files and all I can rely on is:

- any field containing embedded LF characters will be will be contained within double-quotes
- the delimiter will be known in advance
- any double-quotes within a field will be:  
– contained within a quoted field  
– represented as two double-quote characters

Based on this, I think the regex is as simple as it can be.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex019/uploads/powershell/original/1X/385e4f9fe133561ad30a814262fe0e0ae6bc3ef0.png) [@system](https://forums.powershell.org/u/system)\
**Post date:** [July 27, 2024, 1:54pm UTC](https://forums.powershell.org/t/search-for-a-value-in-an-array-of-pscustomobjects/24358/9 "2024-07-27T13:54:21Z")

</div>

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