1
votes

Convertir txt en tableau dans PowerShell

J'ai un script PowerShell et une base de données txt avec un nombre différent d'éléments par ligne.

Mon fichier txt est list.txt:

echo $search[0][0]

Ma recherche de script PowerShell .ps1:

$search = @(("10345","doomsday","life","hope","run","stone"),("10346","ride","latest","metal"))

Alors, comment convertir chaque ligne en élément de tableau? Comme ceci:

#Get file path
$path = Split-Path $script:MyInvocation.MyCommand.Path

$search = @()
Get-Content -LiteralPath "$path\list.txt" | ForEach-Object {
$search += $_
}

Pour fonctionner en tant que:

"10345","doomsday","life","hope","run","stone"
"10346","ride","latest","metal"


2 commentaires

Les citations doivent-elles être supprimées des articles? En d'autres termes; $ search [0] [0] doit-il renvoyer "10345" ou simplement 10345 ?


Merci pour l'attention. J'ai édité mon txt et je n'ai utilisé que des virgules pour séparer les éléments. Avec ce script original ci-dessous, vous devez remplacer les guillemets.


3 Réponses :


3
votes

Utilisez -split . Un extrait de code que vous pouvez déboguer dans ISE ou VSCode ci-dessous.

$x1 = @'
"10345","doomsday","life","hope","run","stone"
"10346","ride","latest","metal"
'@

$data = $x1 -split "`r`n"

$data.Count

$data[0] -split ","

$arr = @()
foreach ($row in $data)
{
    $arr += ,($row -split ",")
}

"arr"
$arr

"0,3"
$arr[0][3]

"1,3"
$arr[1][3]

Ainsi, vous pouvez diviser chaque ligne de votre fichier renvoyé par Get-Content et l'ajouter à votre nouveau tableau qui vous permet de référencer comment vous voulu ...

Il existe d'autres façons d'utiliser vos données en fonction de vos besoins.


1 commentaires

Notez que Get-Content fait déjà la partie -split "` r`n ", de sorte que la division n'est nécessaire que lors du traitement d'une chaîne multiligne.



3
votes

Voici une solution PSv4 + concise:

$search = switch -file $path\list.txt { default { , ($_ -split ',') } }
  • La méthode .ForEach () opère sur chaque ligne lue dans le fichier d'entrée par Get-Content .
  • $ _ -split ',' divise chaque ligne en un tableau de chaînes par séparateur ,
  • , (...) enveloppe ce tableau dans un aux. tableau à élément unique pour garantir que le tableau est effectivement sorti dans son ensemble, ce qui donne un tableau de tableaux en tant que sortie globale.
    • Remarque: Strictement parlant, la méthode .ForEach () génère une collection [System.Collections.ObjectModel.Collection [psobject]] plutôt qu'un tableau PowerShell normal ( [object []] ), mais à toutes fins pratiques, les deux types agissent de la même manière.

Remarque: La .ForEach () méthode a été choisie comme alternative plus rapide à un pipeline avec le ForEach-Object (% ) cmdlet .
Notez que la méthode .ForEach () nécessite de stocker d'abord la collection d'entrée en mémoire dans son ensemble.


Une alternative plus rapide et plus efficace en mémoire, bien que peut-être légèrement obscure consiste à utiliser une instruction switch avec l'option -file :

$search = (Get-Content -LiteralPath $path\list.txt).ForEach({ , ($_ -split ',') })
  • switch -file traite chaque ligne du fichier spécifié.

  • Comme chaque ligne doit être traitée, seule une branche default est utilisée, dans laquelle le fractionnement souhaité est effectué.


7 commentaires

Puisque OP semble être un utilisateur plus récent, j'ai écrit la réponse d'une manière qui peut être facilement exécutée dans un débogueur ligne par ligne. Entre ces 2 réponses, les gens devraient avoir une bonne compréhension de ce scénario.


Légèrement obscur ...? o_O


J'espère bien, @KoryGill. La raison pour laquelle j'ai écrit ma propre réponse est que, même si je pense que la vôtre est utile, je voulais montrer une alternative plus concise, notamment celle qui évite l'utilisation de + = pour construire de manière inefficace un tableau (vous peut avoir fait cela uniquement pour faciliter le débogage, mais je suggère de noter que cette approche devrait être évitée dans le code réel) et se concentre uniquement sur la solution.


oui, sauf si c'est une petite structure, j'évite + = sur un @ () et j'utiliserai toujours ArrayList / etc. merci @ mklement0.


Allez, des choses comme ça font que PowerShell ressemble à Perl.


@KoryGill: Une ArrayList est préférable, mais une alternative plus simple et plus efficace consiste à traiter une instruction foreach comme une expression dont vous pouvez collecter la sortie dans une variable (tableau): [array] $ arr = foreach (...) {...}


@AnsgarWiechers: Bon vieux Perl - j'ai toujours eu un faible pour ça. Blague à part: point pris; la diffusion de l'instruction sur plusieurs lignes peut en aider certains, mais il y a une complexité inhérente à l'instruction switch .



0
votes

En supposant que vous ne souhaitez pas que chaque élément soit cité, vous pouvez envisager de pas en utilisant le -Split opérateur mais en évaluant simplement chaque ligne avec Invoke-Expression cmdlet ou en utilisant un [ScriptBlock] pour ceci:

$Search = Get-Content ".\list.txt" | ForEach-Object {,@(&([ScriptBlock]::Create($_)))}


0 commentaires