Get a variable by dynamic variable name











up vote
1
down vote

favorite
1












How does one access data imported from a CSV file by using dynamic note property names? That is, one doesn't know the colunm names beforehand. They do match a pattern and are extracted from the CSV file when the script runs.



As for an example, consider a CSV file:



"Header 1","Header A","Header 3","Header B"
0,0,0,0
1,2,3,4
5,6,7,8


I'd like to extract only columns that end with a letter. To do this, I read the header row and extract names with a regex like so,



$reader = new-object IO.StreamReader("C:tmpdata.csv")
$line = $reader.ReadLine()
$headers = @()

$line.Split(",") | % {
$m = [regex]::match($_, '("Header [A-Z]")')
if($m.Success) { $headers += $m.value } }


This will get all the column names I care about:



"Header A"
"Header B"


Now, to access a CSV file I import it like so,



$csvData = import-csv "C:tmpdata.csv"


Import-CSV will create a custom object that has properties as per the header row. One can access the fields by NoteProperty names like so,



$csvData | % { $_."Header A" } # Works fine


This obviously requires one to know the column name in advance. I'd like to use colunn names I extracted and stored into the $headers. How would I do that?



Some things I've tried so far



$csvData | % { $_.$headers[0] } # Error: Cannot index into a null array.
$csvData | % { $np = $headers[0]; $_.$np } # Doesn't print anything.
$csvData | % { $_.$($headers[0]) } # Doesn't print anything.


I could change the script like so it will write another a script that does know the column names. Is that my only solution?










share|improve this question




























    up vote
    1
    down vote

    favorite
    1












    How does one access data imported from a CSV file by using dynamic note property names? That is, one doesn't know the colunm names beforehand. They do match a pattern and are extracted from the CSV file when the script runs.



    As for an example, consider a CSV file:



    "Header 1","Header A","Header 3","Header B"
    0,0,0,0
    1,2,3,4
    5,6,7,8


    I'd like to extract only columns that end with a letter. To do this, I read the header row and extract names with a regex like so,



    $reader = new-object IO.StreamReader("C:tmpdata.csv")
    $line = $reader.ReadLine()
    $headers = @()

    $line.Split(",") | % {
    $m = [regex]::match($_, '("Header [A-Z]")')
    if($m.Success) { $headers += $m.value } }


    This will get all the column names I care about:



    "Header A"
    "Header B"


    Now, to access a CSV file I import it like so,



    $csvData = import-csv "C:tmpdata.csv"


    Import-CSV will create a custom object that has properties as per the header row. One can access the fields by NoteProperty names like so,



    $csvData | % { $_."Header A" } # Works fine


    This obviously requires one to know the column name in advance. I'd like to use colunn names I extracted and stored into the $headers. How would I do that?



    Some things I've tried so far



    $csvData | % { $_.$headers[0] } # Error: Cannot index into a null array.
    $csvData | % { $np = $headers[0]; $_.$np } # Doesn't print anything.
    $csvData | % { $_.$($headers[0]) } # Doesn't print anything.


    I could change the script like so it will write another a script that does know the column names. Is that my only solution?










    share|improve this question


























      up vote
      1
      down vote

      favorite
      1









      up vote
      1
      down vote

      favorite
      1






      1





      How does one access data imported from a CSV file by using dynamic note property names? That is, one doesn't know the colunm names beforehand. They do match a pattern and are extracted from the CSV file when the script runs.



      As for an example, consider a CSV file:



      "Header 1","Header A","Header 3","Header B"
      0,0,0,0
      1,2,3,4
      5,6,7,8


      I'd like to extract only columns that end with a letter. To do this, I read the header row and extract names with a regex like so,



      $reader = new-object IO.StreamReader("C:tmpdata.csv")
      $line = $reader.ReadLine()
      $headers = @()

      $line.Split(",") | % {
      $m = [regex]::match($_, '("Header [A-Z]")')
      if($m.Success) { $headers += $m.value } }


      This will get all the column names I care about:



      "Header A"
      "Header B"


      Now, to access a CSV file I import it like so,



      $csvData = import-csv "C:tmpdata.csv"


      Import-CSV will create a custom object that has properties as per the header row. One can access the fields by NoteProperty names like so,



      $csvData | % { $_."Header A" } # Works fine


      This obviously requires one to know the column name in advance. I'd like to use colunn names I extracted and stored into the $headers. How would I do that?



      Some things I've tried so far



      $csvData | % { $_.$headers[0] } # Error: Cannot index into a null array.
      $csvData | % { $np = $headers[0]; $_.$np } # Doesn't print anything.
      $csvData | % { $_.$($headers[0]) } # Doesn't print anything.


      I could change the script like so it will write another a script that does know the column names. Is that my only solution?










      share|improve this question















      How does one access data imported from a CSV file by using dynamic note property names? That is, one doesn't know the colunm names beforehand. They do match a pattern and are extracted from the CSV file when the script runs.



      As for an example, consider a CSV file:



      "Header 1","Header A","Header 3","Header B"
      0,0,0,0
      1,2,3,4
      5,6,7,8


      I'd like to extract only columns that end with a letter. To do this, I read the header row and extract names with a regex like so,



      $reader = new-object IO.StreamReader("C:tmpdata.csv")
      $line = $reader.ReadLine()
      $headers = @()

      $line.Split(",") | % {
      $m = [regex]::match($_, '("Header [A-Z]")')
      if($m.Success) { $headers += $m.value } }


      This will get all the column names I care about:



      "Header A"
      "Header B"


      Now, to access a CSV file I import it like so,



      $csvData = import-csv "C:tmpdata.csv"


      Import-CSV will create a custom object that has properties as per the header row. One can access the fields by NoteProperty names like so,



      $csvData | % { $_."Header A" } # Works fine


      This obviously requires one to know the column name in advance. I'd like to use colunn names I extracted and stored into the $headers. How would I do that?



      Some things I've tried so far



      $csvData | % { $_.$headers[0] } # Error: Cannot index into a null array.
      $csvData | % { $np = $headers[0]; $_.$np } # Doesn't print anything.
      $csvData | % { $_.$($headers[0]) } # Doesn't print anything.


      I could change the script like so it will write another a script that does know the column names. Is that my only solution?







      powershell parameters






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 19 at 9:18









      Ansgar Wiechers

      138k12118181




      138k12118181










      asked Dec 15 '11 at 19:23









      vonPryz

      12.2k23342




      12.2k23342
























          3 Answers
          3






          active

          oldest

          votes

















          up vote
          0
          down vote



          accepted










          the first thing ( and the only one... sorry) that came in my mind is:



          $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[0].name) }


          for get the first's column values and



          $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[1].name) }


          for second column and so on....



          is this what you need?






          share|improve this answer





















          • Almost. It requires one to know the indexes in advance, but can be fixed easily enough by adding a -like search: $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty" -and $_.Name -like $($headers[0])} ).name) }
            – vonPryz
            Dec 16 '11 at 5:48












          • Thanks, this was exactly what I needed.
            – vonPryz
            Dec 16 '11 at 17:09










          • @vonPryz - How is this exactly what you needed? Christian - No offence.
            – manojlds
            Dec 16 '11 at 23:30


















          up vote
          3
          down vote













          I think you want this:



          [string]$headers = $csvdata | gm -MemberType "noteproperty" | 
          ?{ $_.Name -match "Header [a-zA-Z]$"} |
          select -expand Name
          $csvdata | select $headers


          Choose the headers that match the condition (in this case, ones ending with characters) and then get the csv data for those headers.






          share|improve this answer




























            up vote
            0
            down vote













            you can use custom script to parse csv manually:



            $content = Get-Content "C:tmpdata.csv"
            $header = $content | Select -first 1
            $columns = $header.Split(",")
            $indexes = @()
            for($i; $i -lt $columns.Count;$i++)
            {
            # to verify whether string end with letter matches this regex: "[A-Za-z]$"
            if ($column[$i] -match "[A-Za-z]$")
            {
            $indexes += $i
            }
            }

            $outputFile = "C:tmpoutdata.csv"
            Remove-Item $outputFile -ea 0
            foreach ($line in $content)
            {
            $output = ""
            $rowcol = $line.Split(",")
            [string]::Join(",", ($indexes | foreach { $rowcol[$_] })) | Add-Content $outputFile
            }





            share|improve this answer





















              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8525481%2fget-a-variable-by-dynamic-variable-name%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              3 Answers
              3






              active

              oldest

              votes








              3 Answers
              3






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              0
              down vote



              accepted










              the first thing ( and the only one... sorry) that came in my mind is:



              $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[0].name) }


              for get the first's column values and



              $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[1].name) }


              for second column and so on....



              is this what you need?






              share|improve this answer





















              • Almost. It requires one to know the indexes in advance, but can be fixed easily enough by adding a -like search: $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty" -and $_.Name -like $($headers[0])} ).name) }
                – vonPryz
                Dec 16 '11 at 5:48












              • Thanks, this was exactly what I needed.
                – vonPryz
                Dec 16 '11 at 17:09










              • @vonPryz - How is this exactly what you needed? Christian - No offence.
                – manojlds
                Dec 16 '11 at 23:30















              up vote
              0
              down vote



              accepted










              the first thing ( and the only one... sorry) that came in my mind is:



              $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[0].name) }


              for get the first's column values and



              $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[1].name) }


              for second column and so on....



              is this what you need?






              share|improve this answer





















              • Almost. It requires one to know the indexes in advance, but can be fixed easily enough by adding a -like search: $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty" -and $_.Name -like $($headers[0])} ).name) }
                – vonPryz
                Dec 16 '11 at 5:48












              • Thanks, this was exactly what I needed.
                – vonPryz
                Dec 16 '11 at 17:09










              • @vonPryz - How is this exactly what you needed? Christian - No offence.
                – manojlds
                Dec 16 '11 at 23:30













              up vote
              0
              down vote



              accepted







              up vote
              0
              down vote



              accepted






              the first thing ( and the only one... sorry) that came in my mind is:



              $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[0].name) }


              for get the first's column values and



              $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[1].name) }


              for second column and so on....



              is this what you need?






              share|improve this answer












              the first thing ( and the only one... sorry) that came in my mind is:



              $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[0].name) }


              for get the first's column values and



              $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[1].name) }


              for second column and so on....



              is this what you need?







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Dec 15 '11 at 20:21









              CB.

              43.7k593114




              43.7k593114












              • Almost. It requires one to know the indexes in advance, but can be fixed easily enough by adding a -like search: $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty" -and $_.Name -like $($headers[0])} ).name) }
                – vonPryz
                Dec 16 '11 at 5:48












              • Thanks, this was exactly what I needed.
                – vonPryz
                Dec 16 '11 at 17:09










              • @vonPryz - How is this exactly what you needed? Christian - No offence.
                – manojlds
                Dec 16 '11 at 23:30


















              • Almost. It requires one to know the indexes in advance, but can be fixed easily enough by adding a -like search: $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty" -and $_.Name -like $($headers[0])} ).name) }
                – vonPryz
                Dec 16 '11 at 5:48












              • Thanks, this was exactly what I needed.
                – vonPryz
                Dec 16 '11 at 17:09










              • @vonPryz - How is this exactly what you needed? Christian - No offence.
                – manojlds
                Dec 16 '11 at 23:30
















              Almost. It requires one to know the indexes in advance, but can be fixed easily enough by adding a -like search: $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty" -and $_.Name -like $($headers[0])} ).name) }
              – vonPryz
              Dec 16 '11 at 5:48






              Almost. It requires one to know the indexes in advance, but can be fixed easily enough by adding a -like search: $csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty" -and $_.Name -like $($headers[0])} ).name) }
              – vonPryz
              Dec 16 '11 at 5:48














              Thanks, this was exactly what I needed.
              – vonPryz
              Dec 16 '11 at 17:09




              Thanks, this was exactly what I needed.
              – vonPryz
              Dec 16 '11 at 17:09












              @vonPryz - How is this exactly what you needed? Christian - No offence.
              – manojlds
              Dec 16 '11 at 23:30




              @vonPryz - How is this exactly what you needed? Christian - No offence.
              – manojlds
              Dec 16 '11 at 23:30












              up vote
              3
              down vote













              I think you want this:



              [string]$headers = $csvdata | gm -MemberType "noteproperty" | 
              ?{ $_.Name -match "Header [a-zA-Z]$"} |
              select -expand Name
              $csvdata | select $headers


              Choose the headers that match the condition (in this case, ones ending with characters) and then get the csv data for those headers.






              share|improve this answer

























                up vote
                3
                down vote













                I think you want this:



                [string]$headers = $csvdata | gm -MemberType "noteproperty" | 
                ?{ $_.Name -match "Header [a-zA-Z]$"} |
                select -expand Name
                $csvdata | select $headers


                Choose the headers that match the condition (in this case, ones ending with characters) and then get the csv data for those headers.






                share|improve this answer























                  up vote
                  3
                  down vote










                  up vote
                  3
                  down vote









                  I think you want this:



                  [string]$headers = $csvdata | gm -MemberType "noteproperty" | 
                  ?{ $_.Name -match "Header [a-zA-Z]$"} |
                  select -expand Name
                  $csvdata | select $headers


                  Choose the headers that match the condition (in this case, ones ending with characters) and then get the csv data for those headers.






                  share|improve this answer












                  I think you want this:



                  [string]$headers = $csvdata | gm -MemberType "noteproperty" | 
                  ?{ $_.Name -match "Header [a-zA-Z]$"} |
                  select -expand Name
                  $csvdata | select $headers


                  Choose the headers that match the condition (in this case, ones ending with characters) and then get the csv data for those headers.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Dec 15 '11 at 20:50









                  manojlds

                  210k46368357




                  210k46368357






















                      up vote
                      0
                      down vote













                      you can use custom script to parse csv manually:



                      $content = Get-Content "C:tmpdata.csv"
                      $header = $content | Select -first 1
                      $columns = $header.Split(",")
                      $indexes = @()
                      for($i; $i -lt $columns.Count;$i++)
                      {
                      # to verify whether string end with letter matches this regex: "[A-Za-z]$"
                      if ($column[$i] -match "[A-Za-z]$")
                      {
                      $indexes += $i
                      }
                      }

                      $outputFile = "C:tmpoutdata.csv"
                      Remove-Item $outputFile -ea 0
                      foreach ($line in $content)
                      {
                      $output = ""
                      $rowcol = $line.Split(",")
                      [string]::Join(",", ($indexes | foreach { $rowcol[$_] })) | Add-Content $outputFile
                      }





                      share|improve this answer

























                        up vote
                        0
                        down vote













                        you can use custom script to parse csv manually:



                        $content = Get-Content "C:tmpdata.csv"
                        $header = $content | Select -first 1
                        $columns = $header.Split(",")
                        $indexes = @()
                        for($i; $i -lt $columns.Count;$i++)
                        {
                        # to verify whether string end with letter matches this regex: "[A-Za-z]$"
                        if ($column[$i] -match "[A-Za-z]$")
                        {
                        $indexes += $i
                        }
                        }

                        $outputFile = "C:tmpoutdata.csv"
                        Remove-Item $outputFile -ea 0
                        foreach ($line in $content)
                        {
                        $output = ""
                        $rowcol = $line.Split(",")
                        [string]::Join(",", ($indexes | foreach { $rowcol[$_] })) | Add-Content $outputFile
                        }





                        share|improve this answer























                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          you can use custom script to parse csv manually:



                          $content = Get-Content "C:tmpdata.csv"
                          $header = $content | Select -first 1
                          $columns = $header.Split(",")
                          $indexes = @()
                          for($i; $i -lt $columns.Count;$i++)
                          {
                          # to verify whether string end with letter matches this regex: "[A-Za-z]$"
                          if ($column[$i] -match "[A-Za-z]$")
                          {
                          $indexes += $i
                          }
                          }

                          $outputFile = "C:tmpoutdata.csv"
                          Remove-Item $outputFile -ea 0
                          foreach ($line in $content)
                          {
                          $output = ""
                          $rowcol = $line.Split(",")
                          [string]::Join(",", ($indexes | foreach { $rowcol[$_] })) | Add-Content $outputFile
                          }





                          share|improve this answer












                          you can use custom script to parse csv manually:



                          $content = Get-Content "C:tmpdata.csv"
                          $header = $content | Select -first 1
                          $columns = $header.Split(",")
                          $indexes = @()
                          for($i; $i -lt $columns.Count;$i++)
                          {
                          # to verify whether string end with letter matches this regex: "[A-Za-z]$"
                          if ($column[$i] -match "[A-Za-z]$")
                          {
                          $indexes += $i
                          }
                          }

                          $outputFile = "C:tmpoutdata.csv"
                          Remove-Item $outputFile -ea 0
                          foreach ($line in $content)
                          {
                          $output = ""
                          $rowcol = $line.Split(",")
                          [string]::Join(",", ($indexes | foreach { $rowcol[$_] })) | Add-Content $outputFile
                          }






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Dec 15 '11 at 20:51









                          Tomas Panik

                          2,7411828




                          2,7411828






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f8525481%2fget-a-variable-by-dynamic-variable-name%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                              Alcedinidae

                              Origin of the phrase “under your belt”?