1

Revised efforts based on supplied answers:

PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> Get-Content ./case.csv  | ForEach-Object ToUpper                            
FJKDLA,W
FKDSLAJF,FDJK;A
NLK;NBF;SDJF,DGDF
VNL;KKDF,BGNGFN
NVCL;V,RGS
NVKL;,THRN
VLKDF,TMMJYMF
FJDK,FDJK;A
PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> Get-Content ./case.csv  | ForEach-Object ToLower 
fjkdla,w
fkdslajf,fdjk;a
nlk;nbf;sdjf,dgdf
vnl;kkdf,bgngfn
nvcl;v,rgs
nvkl;,thrn
vlkdf,tmmjymf
fjdk,fdjk;a
PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> $TextInfo = (New-Object System.Globalization.CultureInfo("en-US")).TextInfo;
PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> Get-Content ./case.csv  | ForEach-Object ToTitleCase                         
PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> pwsh --version
PowerShell 7.3.4
PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 23.04
Release:    23.04
Codename:   lunar
PS /home/nicholas/powershell> 

My main concern is more converting to TitleCase, and, ideally, from the REPL console rather than a script file. I haven't been able update efforts on targeting a specific column.

By the REPL console I mean the interactive shell, if that makes sense.

All answers and comments have been extremely helpful and appreciated.

additional info:

PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> Get-Culture                                        

LCID             Name             DisplayName
----             ----             -----------
1033             en-US            English (United States)

PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> (Get-Culture).TextInfo.ToTitleCase($_.fjkdla) 

PS /home/nicholas/powershell> 
PS /home/nicholas/powershell> (Get-Culture).TextInfo.ToTitleCase("hmm")     
Hmm
PS /home/nicholas/powershell> 

Which looks to be the desired output for a single string. Not sure how to iterate the CSV file above from the console, however.

  • Get-Content ./case.csv | ForEach-Object ToUpper works but I'd like to use the one loaded in memory. see https://stackoverflow.com/a/38401544/4531180 even better would to use the ToTitleCase function – Nicholas Saunders Jun 13 '23 at 16:04
  • 2
    `$csv.ForEach{$_.Name = $_.Name.ToLower()}`? – iRon Jun 13 '23 at 16:33
  • 2
    [**Note:** The syntax requires the usage of a script block. Parentheses are optional if the scriptblock is the only parameter. Also, there must not be a space between the method and the opening parenthesis or brace.](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/about/about_arrays#foreach) – iRon Jun 13 '23 at 16:42
  • that looks like the best solution @iRon and I like the dot for invoking a method. I'll try that with toTitleCase as well. – Nicholas Saunders Jun 14 '23 at 22:57

3 Answers3

5

Update in response to the now substantially changed question:

  • Your original question, as still reflected in the title, was about CSV data, and targeting a specific column. Given that you originally used Import-Csv, an OO approach was called for, as shown in the next section.

    • To target a specific column you need to know its exact name (except that case doesn't matter).
    • If your CSV file lacks headers, i.e. an initial line with column names, you need to:
      • Manually supply column names, via Import-Csv's -Header parameter, e.g.: Import-Csv ./case.csv -Header Name, Value.
      • Then refer to those column names in a ForEach-Object script block, as shown below (e.g., $_.Name)
  • Your updated question, which uses plain-text processing of your CSV file using Get-Content, seemingly attempts to convert all column values to title case; to that end, use the following approach:

     $textInfo = (Get-Culture).TextInfo
     Get-Content ./case.csv | ForEach-Object { $textInfo.ToTitleCase($_) }
    
     # Alternatively, if performance doesn't matter and you don't want to 
     # create an aux. variable, to reduce the interactive typing effort:
     Get-Content ./case.csv | ForEach-Object { (Get-Culture).TextInfo.ToTitleCase($_) }
    

Answer to the original, OO question:

To convert a single, known column to title case in a single pipeline, be sure to use its exact name (though case doesn't matter); using your sample CSV's first column name as an example:

Import-Csv ./case.csv |
  ForEach-Object {
    $_.fjkdla = (Get-Culture).TextInfo.ToTitleCase($_.fjkdla)
    $_ # Output the modified object.
  }

This outputs the modified objects parsed from the CSV file and outputs them directly; by default, they print to the screen; prepend, e.g., $csv = to the pipeline to capture its output in variable $csv.

Note:

  • If you've already imported your CSV file and saved the resulting objects to array $csv, iRon's suggestion is a simple and efficient solution, using the intrinsic .ForEach() method:

    # Transforms the objects stored in $csv in-place.
    $csv.ForEach({ $_.fjkdla = (Get-Culture).TextInfo.ToTitleCase($_.fjkdla) })
    

To methodically convert all columns to title case, without needing to know the column (property) values ahead of time, using the intrinsic psobject property:

Import-Csv ./case.csv |
  ForEach-Object {
    # Iterate over all properties and modify their values.
    foreach ($prop in $_.psobject.Properties) {
      $prop.Value = (Get-Culture).TextInfo.ToTitleCase($prop.Value)
    }
    $_ # Output the modified object.
  }

Note:

  • For simplicity and to minimize the interactive typing effort, the above solutions make a call to Get-Culture to obtain the title-casing method not only for each object, but, in the last case, also for each property of each object, which is inefficient.

Better-performing alternative, which caches a reference to the method and invokes it with .Invoke():

$titleCaseMethod = (Get-Culture).TextInfo.ToTitleCase
Import-Csv ./case.csv |
  ForEach-Object {
    # Iterate over all properties and modify their values.
    foreach ($prop in $_.psobject.Properties) {
      $prop.Value = $titleCaseMethod.Invoke($prop.Value)
    }
    $_ # Output the modified object.
  }
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Greatly appreciate info about Get-Culture. Would you be able to show the iteration from a console? I'm using Linux if that has an effect on anything. – Nicholas Saunders Jun 14 '23 at 15:35
  • 1
    @NicholasSaunders, please see the section I've added to the top of this answer. In the future, please don't substantially rewrite your question after answers have been given, as it invalidates the latter and is likely to confuse future readers. – mklement0 Jun 14 '23 at 15:55
1

The Get-Culture PowerShell cmdlet doesn't seem to exist on the Replit PowerShell console. It has a TextInfo method you can use to get Title Case, as @mklement shows. The below code worked for me in Replit console, however.

CSV File:

Name,Column2
TEsT tEST TeST,stuff
tEST2 TesT2 test2,more stuff

REPLIT Console Code:

$TextInfo = (New-Object System.Globalization.CultureInfo("en-US")).TextInfo;

$csv = Import-Csv -Path 'REPL.csv' | 
    ForEach-Object { 
        $_.Name = $TextInfo.toTitleCase($_.Name)
        $_ 
    }

$csv

Output:

Name                                       Column2                                  
----                                       -------                                  
Test Test Test                             stuff                               
Test2 Test2 Test2                          more stuff 
Grok42
  • 196
  • 4
  • Assuming that you're talking about https://replit.com/ (which I don't think the OP has in mind): Note that their PowerShell template seems to be based on the OBSOLETE Pash project (https://github.com/Pash-Project/Pash/), a community attempt at an open-source PowerShell implementation that had severe limitations and was abandoned when Microsoft itself took PowerShell open-source and cross-platform (https://github.com/PowerShell/PowerShell). – mklement0 Jun 13 '23 at 18:36
  • Absolutely, TitleCase looks to be exactly what I'm looking to use. Would you be able to show the iteration from the console? On Linux I type "pwsh" from a bash console for an interactive session. – Nicholas Saunders Jun 14 '23 at 15:37
0

This seems to work:

PS C:\Users\Nick\Documents>
PS C:\Users\Nick\Documents> $csv = import-csv .\abcd.csv
PS C:\Users\Nick\Documents>
PS C:\Users\Nick\Documents> $csv

alpha       beta       charlie    delta
-----       ----       -------    -----
sdkljgsdf   bdgfhgfnhm ngfgfddfsg dfhgsdfg
gfjd;saklbf dfbdfgfn   vfsdafdfbn fgjtyj
bdgfkl;     dsfsd      vgngfas    dsfhgtj
dsbmnkl     nggfn      bfdsda     edtshdgf
asdfkl      sdagfdfh   vbdfdngt   ngfggj


PS C:\Users\Nick\Documents>
PS C:\Users\Nick\Documents> $textInfo = (Get-Culture).TextInfo
PS C:\Users\Nick\Documents>
PS C:\Users\Nick\Documents> $csv | ForEach-Object { $_.alpha = $textInfo.ToTitleCase($_.alpha) }
PS C:\Users\Nick\Documents>
PS C:\Users\Nick\Documents> $csv

alpha       beta       charlie    delta
-----       ----       -------    -----
Sdkljgsdf   bdgfhgfnhm ngfgfddfsg dfhgsdfg
Gfjd;Saklbf dfbdfgfn   vfsdafdfbn fgjtyj
Bdgfkl;     dsfsd      vgngfas    dsfhgtj
Dsbmnkl     nggfn      bfdsda     edtshdgf
Asdfkl      sdagfdfh   vbdfdngt   ngfggj


PS C:\Users\Nick\Documents>

For my purposes, at least. Just using a different PC.