Powershell neden dize dizisini bir öğe içeren bir dizeye sessizce dönüştürüyor?


33

C: \ 'deki klasörleri adında' og 'ile arayan aşağıdaki Powershell betiğini göz önünde bulundurun:

PS C: \> (ls |% {$ _. Name} |? {$ _. İçeriyor ("og")})
PerfLogs
Program dosyaları
setup.log

Şimdi tek bir öğeyi almak için aramayı daraltıyorum:

PS C: \> (ls |% {$ _. Name} |? {$ _. İçeriyor ("Prog")})
Program dosyaları

Garip olan, ilk işlemin bir dizi vermesi, ikinci işlemin (ki IMHO semantik olarak aynı işlem olduğu için, aynı sonuç sonucunu vermesi gerekir) bir dizi vermesidir . Bu aşağıdaki sonuçta görülebilir:

PS C: \> (ls |% {$ _. Ad} |? {$ _. İçeriyor ("og")}). Uzunluk
3
PS C: \> (ls |% {$ _. Name} |? {$ _. İçeriyor ("Prog")}). Uzunluk
13

Bu çok rahatsız edici olabilir, çünkü görünüşe göre 'og' ile eşleşen, 'Prog' ile eşleşen klasörlerden daha az klasör var.

Açıkçası, PowerShell tek bir nesneye diziyi tek bir nesneye dolaylı olarak 'kutusundan çıkardı' ve hiçbir zaman bir uzunluk dizisi elde etmiyoruz. m bir dizi ile ilgilenip ilgilenmiyor.

Bunun olmasını nasıl önleyebilirim? Nasıl anlaştın onunla birlikte?


Bunlar StackOverflow'tan yardımcı olabilir: stackoverflow.com/questions/1827862/… stackoverflow.com/questions/1390782/… Eğer boru bağlantısı yapmıyorsanız $_.Contains, o zaman %{,,$_.Name}çalışır ...
Bob

Yanıtlar:


56

Açıkça, PowerShell, tek bir nesne dizisini tek bir nesneye dolaylı olarak “kutudan çıkarır”.

Ve sıfır öğesi sonuçlanır $null.

Bunun olmasını nasıl önleyebilirim?

Yapamazsın

Nasıl anlaştın onunla birlikte?

@(...)Bir koleksiyona zorlamak için dizi yapıcısını ( ) kullanın (muhtemelen sıfır veya bir öğe ile) dönüş:

$res = @(ls | %{$_.Name} | ?{$_.Contains("Prog")})

Teşekkürler, bu mükemmel! 15 üne sahip olduğumda hemen oy atacağım.
Cheesus SO Monica zarar durdurmak

2
Bunu "zorlayabileceğinden" emin değilim. @(1) | ConvertTo-Jsonhala 1yerine döner [1].
Marc

@Marc: ConvertTo-Jsonhiçbir zaman bir koleksiyon döndürmez: tüm girişi okur ve tek bir dizgeye dönüştürür. Giriş nesnelerinin ayrı ayrı dönüştürülmesini istiyorsanız, her birini ayrı ayrı işlemeniz gerekir.
Richard,

1
@ Richard, yanlış anladığını düşünüyorum: Ben ve diğerleri, temel olarak tüm nesnenin (yani koleksiyonun) seri hale getirilmesini (örneğin, harici ısrar için) istiyorum. Koleksiyondaki her bir nesneyi ayrı ayrı işlemekle ilgilenmiyoruz. ConvertTo-Json, çalıştırıldığı takdirde ConvertFrom-Json'a boş bir dizi / koleksiyon da olsa orijinal nesneyi döndüren bir dize döndürmelidir.
Marc

@Marc Bu sorunun amacı, tek bir eleman dizisinin o eleman olarak ele alınmasından kaçınmaktır (bu, daha sonraki PSH değişikliklerinden dolayı daha az sorun olur: sorunun tarihine dikkat edin). Tamamen farklı bir durumdan (bir koleksiyonu tek bir nesne olmaya zorlayan) bahsediyorsunuz, bu yüzden yanlış anlamıyorum.
Richard,

2

Bu PowerShell v3'te çözüldü:

http://blogs.microsoft.co.il/blogs/scriptfanatic/archive/2012/03/19/Counting-objects-in-PowerShell-3.0.aspx

Yan notta, bir adın joker karakter kullanarak bir şey içerip içermediğini görebilirsiniz:

PS> ls *og*

6
Shay , henüz cevaplar hakkında yorum yapamam, ama ifaden doğru değil. PowerShell öğeleri hala içeriyor, ancak sizin de belirttiğiniz gibi, tek öğelere "Sayı" değeri verildi. Yine de, tek öğe sonuçları hala kutusuz. Yukarıdaki örneği PS 3'e karşı test edebilir ve sonuçları görebilirsiniz.
Tohuw

1
Davranış PS 5'te hala aynıdır.
MEMark

Evet, def hala mevcut
James Wiseman

1
Bu davranış hala PS 6.0.1'de aynıdır
spuder,

2

Bu iki sonuç arasındaki farkı not edin:

PS C:\> ConvertTo-Json -InputObject @(1)
[
    1
]
PS C:\> @(1)|ConvertTo-Json
1
PS C:\>

Mesele şu ki, 'kutudan çıkarma' boru işlemi tarafından yapılıyor. ConvertTo-Json, boru yerine InputObject kullanırsak, nesneyi hala bir dizi olarak görüyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.