سؤال

آخر مرة حصلت على الخلط على فكرة Powershell. تخصيص مجموعات بفارغ الصبر، كيث إغراء به مثل:

يؤدي وضع النتائج (صفيف) داخل تعبير تجمع (أو فرعي، على سبيل المثال $ ()) مؤهلا مرة أخرى إلى عدم انسضار.

لقد اتخذت هذه النصيحة إلى القلب، ولكن لا يزال يجد نفسي غير قادر على شرح عدد قليل من Esoterica. على وجه الخصوص، يبدو أن عامل التشغيل التنسيق لا يلعبه القواعد.

$lhs = "{0} {1}"

filter Identity { $_ }
filter Square { ($_, $_) }
filter Wrap { (,$_) }
filter SquareAndWrap { (,($_, $_)) }

$rhs = "a" | Square        
# 1. all succeed
$lhs -f $rhs
$lhs -f ($rhs)
$lhs -f $($rhs)
$lhs -f @($rhs)

$rhs = "a" | Square | Wrap       
# 2. all succeed
$lhs -f $rhs
$lhs -f ($rhs)
$lhs -f $($rhs)
$lhs -f @($rhs)

$rhs = "a" | SquareAndWrap       
# 3. all succeed
$lhs -f $rhs
$lhs -f ($rhs)
$lhs -f $($rhs)
$lhs -f @($rhs)

$rhs = "a", "b" | SquareAndWrap       
# 4. all succeed by coercing the inner array to the string "System.Object[]"
$lhs -f $rhs
$lhs -f ($rhs)
$lhs -f $($rhs)
$lhs -f @($rhs)

"a" | Square | % {
    # 5. all fail
    $lhs -f $_
    $lhs -f ($_)
    $lhs -f @($_)
    $lhs -f $($_)            
}

"a", "b" | Square | % {
    # 6. all fail
    $lhs -f $_
    $lhs -f ($_)
    $lhs -f @($_)
    $lhs -f $($_)            
}

"a" | Square | Wrap | % {
    # 7. all fail
    $lhs -f $_
    $lhs -f ($_)
    $lhs -f @($_)
    $lhs -f $($_)            
}

"a", "b" | Square | Wrap | % {
    # 8. all fail
    $lhs -f $_
    $lhs -f ($_)
    $lhs -f @($_)
    $lhs -f $($_)            
}

"a" | SquareAndWrap | % {
    # 9. only @() and $() succeed
    $lhs -f $_
    $lhs -f ($_)
    $lhs -f @($_)
    $lhs -f $($_)            
}

"a", "b" | SquareAndWrap | % {
    # 10. only $() succeeds
    $lhs -f $_
    $lhs -f ($_)
    $lhs -f @($_)
    $lhs -f $($_)            
}

تطبيق نفس الأنماط التي رأيناها في السؤال السابق، من الواضح لماذا تتصرف الحالات مثل # 1 و # 5 مختلفة: يشير مشغل خطوط الأنابيب إلى تشغيل محرك البرنامج النصي إلى مستوى آخر، في حين أن عامل التعيين لا يفعل ذلك. بوضع طريقة أخرى، كل ما يكمن بين اثنين | 'S تعبير مجمعة، تماما كما لو كان في الداخل ().

# all of these output 2
("a" | Square).count                       # explicitly grouped
("a" | Square | measure).count             # grouped by pipes
("a" | Square | Identity).count            # pipe + ()
("a" | Square | Identity | measure).count  # pipe + pipe

لنفس السبب، الحالة رقم 7 ليست تحسنا أكثر من 5. أي محاولة لإضافة اضافية لف سيتم تفسيرها على الفور من قبل الأنابيب الإضافية. Ditto # 8 vs # 6. محبطة قليلا، لكنني على متن الطائرة حتى هذه النقطة.

الأسئلة المتبقية:

  • لماذا لا تحب الحالة # 3 نفس المصير مثل # 4؟ $ rhs. يجب أن تعقد الصفيف المتداخل (، (""، "أ")) لكن مستوىها الخارجي هو الحصول على غير المنضد ... في مكان ما ...
  • ما الذي يحدث مع مختلف مشغلي التجمع في # 9-10؟ لماذا يتصرفون بشكل خاطئ، ولماذا يحتاجون على الإطلاق؟
  • لماذا لا تفشل في القضية # 10 تتحلل بأمان مثل # 4 يفعل؟
هل كانت مفيدة؟

المحلول

حسنا، هناك خطأ في ذلك بالتأكيد. (لقد كتبت للتو صفحة على wiki poshcode عن ذلك أمس، في الواقع، وهناك علة على الاتصال).

الإجابات أولا، المزيد من الأسئلة في وقت لاحق:

للحصول على سلوك متسق من المصفوفات مع -f تنسيق السلسلة، ستحتاج إلى جعل 100٪ متأكد من أنها psoBjects. اقتراحي هو القيام بذلك عند تعيينها. أنه مفترض يتعين القيام به تلقائيا بواسطة PowerShell، ولكن لسبب ما لم يتم ذلك حتى يتمكن من الوصول إلى خاصية أو شيء ما (كما هو موثق في ذلك Wiki Page. و حشرة). على سبيل المثال ( <##> هو موجي الخاص بي):

<##> $a = 1,2,3
<##> "$a"
1 2 3

<##> $OFS = "-"  # Set the Output field separator
<##> "$a"
1-2-3

<##> "{0}" -f $a
1 

<##> $a.Length
3 

<##> "{0}" -f $a
1-2-3

# You can enforce correct behavior by casting:
<##> [PSObject]$b = 1,2,3
<##> "{0}" -f $a
1-2-3

لاحظ أنه عندما تكون قد قمت بذلك، فلن يتم إلغاء المنصوص عليه عند المرور إلى -F ولكن بدلا من ذلك سيكون الإخراج بشكل صحيح - الطريقة التي ستكون بها إذا وضعت المتغير في السلسلة مباشرة.

لماذا لا تحب الحالة # 3 نفس المصير مثل # 4؟ يجب على $ RHS الاستمرار بمجموعة متداخلة (، ("A"، "A")) ولكن مستواها الخارجي هو الحصول على غير المنضد ... في مكان ما ...

النسخة البسيطة من الإجابة هي أن كلا # 3 و # 4 يتم عرضها. الفرق هو أنه في 4، المحتويات الداخلية هي صفيف (حتى بعد الصفيف الخارجي غير منضوض):

$rhs = "a" | SquareAndWrap
$rhs[0].GetType()  # String

$rhs = "a","b" | SquareAndWrap
$rhs[0].GetType()  # Object[]

ما الذي يحدث مع مختلف مشغلي التجمع في # 9-10؟ لماذا يتصرفون بشكل خاطئ، ولماذا يحتاجون على الإطلاق؟

كما قلت في وقت سابق، يجب أن تعتمد مجموعة معلمة واحدة بالتنسيق ويجب أن تكون إخراج باستخدام قواعد تنسيق سلسلة PowerShell (أي: مفصولة $OFS) تماما كما لو كنت وضعت $ _ في السلسلة مباشرة ... لذلك، عندما تتصرف PowerShell بشكل صحيح، $lhs -f $rhs سوف تفشل إذا كانت $ lhs تحتوي على حامليين مكان.

بالطبع، لاحظنا بالفعل أن هناك خطأ في ذلك.

ومع ذلك، لا أرى أي شيء غير منتظم، ومع ذلك: @ () و $ () العمل نفسه لمدة 9 و 10 بقدر ما أستطيع أن أرى (الفرق الرئيسي، في الواقع، هو النسب بالطريقة التي لا تتخلى عنها. في

> $rhs = "a", "b" | SquareAndWrap
> $rhs | % { $lhs -f @($_); " hi " }
a a
 hi 
b b
 hi 

> $rhs | % { $lhs -f $($_); " hi " }
a a
 hi 
b b
 hi     

# Is the same as:
> [String]::Format( "{0} {1}", $rhs[0] ); " hi "
a a
 hi 

> [String]::Format( "{0} {1}", $rhs[1] ); " hi "
b b
 hi     

لذلك ترى الخطأ هو أن @ () أو $ () سيؤدي إلى تمرير الصفيف ك [كائن []] إلى استدعاء تنسيق السلسلة بدلا من PSOBJECT الذي يحتوي على قيم خاصة إلى سلسلة.

لماذا لا تفشل في القضية # 10 تتحلل بأمان مثل # 4 يفعل؟

هذا هو في الأساس نفس الخطأ، في مظهر مختلف. يجب ألا يخرج المصفوفات أبدا ك "System.Object [] في PowerShell إلا إذا اتصلت بدولي يدويا .ToString() الطريقة، أو اجتيازها إلى String.Format () مباشرة ... والسبب في القيام به في # 4 هو هذا الخطأ: فشل PowerShell في تمديدها كشركة PSOJBects قبل تمريرها إلى مكالمة String.Format.

يمكنك رؤية هذا إذا قمت بالوصول إلى خاصية الصفيف قبل اجتيازها، أو إلقاؤها على PSOBject كما في امتحاناتي الأصلية. من الناحية الفنية، فإن الأخطاء في # 10 هي الإخراج الصحيح: أنت تمر بشيء واحد فقط (صفيف) إلى String.format، عندما يتوقع شيئين. إذا قمت بتغيير LHS $ الخاص بك إلى "{0}" فقط، فسترى الصفيف المنسق مع $ من


أتساءل على الرغم من أي سلوك هل مثل والذي تعتقد أنه صيح, ، النظر في المثال الأول؟ أعتقد أن الإخراج الذي تم فصله $ من $ هو الصحيح، بدلا من عدم الالتزام بالمصفيف كما يحدث إذا كنت @ (التفاف)، أو إلقاء عليه [كائن []] (بالمناسبة، لاحظ ما يحدث إذا قمت بإلقاء ذلك على [INT [INT [INT [INT) ]] هو مختلف سلوك عربات التي تجرها الدواب):

> "{0}" -f [object[]]$a
1

> "{0}, {1}" -f [object[]]$a  # just to be clear...
1,2

>  "{0}, {1}" -f [object[]]$a, "two"  # to demonstrate inconsistency
System.Object[],two

> "{0}" -f [int[]]$a
System.Int32[]

أنا متأكد من أن الكثير من البرامج النصية قد كتبت بشكل غير معروف باستفادة من هذا الخطأ، لكنه لا يزال يبدو واضحا بالنسبة لي أن يحدث ذلك يحدث في فقط لأكون واضحا مثال ليس السلوك الصحيح، ولكن يحدث لأنه، على المكالمة (داخل جوهر PowerShell) إلى .NET String.Format( "{0}", a ) ... $a هو object[] ما هي السلسلة .format المتوقعة كما هي المعلمة Params ...

أعتقد أنه يجب أن تكون ثابتة. إذا كانت هناك أي رغبة في الحفاظ على "وظائف" غير مثبتة على الصفيف، فينبغي القيام به باستخدام المشغل @ فولكس، أليس كذلك؟

نصائح أخرى

لن يفعل أي مربع لا التفاف ما تحاوله في # 5 و 7 بغض النظر عما إذا كنت قد وضعت مجموعة داخل تعبير تجميع () كما تفعل في مربع أو تستخدم مشغل الفاصلة كما تفعل في التفاف، متى يمكنك استخدام هذه الوظائف في خط الأنابيب مخرجاتها غير مقصودة حيث تتغذى على مرحلة الأنابيب التالية واحدة في وقت واحد. وبالمثل في 6 و 8، لا يهمك أن الأنبوب في كائنات متعددة، سيقوم كل من المربع والتفاف بإطعامهم في وقت واحد في مرحلة ما لديك.

يبدو أن الحالات 9 و 10 تشير إلى علة في بوبرشيل. خذ مقتطف تعديل هذا وحاوله:

"a" | SquareAndWrap | % {    
    # 9. only @() and $() succeed  
    $_.GetType().FullName
    $_.Length
    $lhs -f [object[]]$_
    $lhs -f [object[]]($_)    
    $lhs -f @($_)   
    $lhs -f $($_)            
}

إنها تعمل. كما يوضح أن Foreach IndachD يتلقى كائنا [] الحجم 2 $_ يجب أن تعمل دون صب (كائن []] أو التفاف في فرعي أو فرعي صفيف. لقد رأينا بعض الأخطاء V2 المتعلقة PSOBJECTS وليس غير ملوث بشكل صحيح وهذا يبدو أنه مثيل آخر لذلك. إذا قمت بفحص PSOBJECT يدويا يعمل على سبيل المثال $_.psobject.baseobject.

أنا "أعتقد" ما أنت تصويره في التفاف هو:

function Wrap2 { Begin {$coll = @();} Process {$coll += $_} End {,$coll} }

سيؤدي ذلك إلى تجميع جميع مدخلات الأنابيب ثم إخراجه كصفيف واحد. سيعمل هذا في القضية 8 ولكنك لا تزال بحاجة إلى الإدلاء إلى [كائن []] على أول استخدامتين لل -f المشغل أو العامل.

راجع للشغل التجاري في كل من المربع والالتفاف والجانبي الخارجي في SquareanDwrap غير ضروري.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top