Powershell: تحليل / تمرير المعلمات: الرموز المميزة غير المقتبسة التي تبدو مثل وسيطات مسماة بنقطتين حيث يتم تقسيم الفاصل إلى قسمين عند تمريره بشكل غير مباشر عبر $ Args /Args

تم إنشاؤها على ١١ مارس ٢٠١٨  ·  3تعليقات  ·  مصدر: PowerShell/PowerShell

ذات صلة: # 6291 و # 6292 و # 4624

المتابعة من https://github.com/PowerShell/PowerShell/issues/6292#issuecomment -371344550:

ملاحظة: الرموز المميزة المعنية ، مثل -foo:bar ، _look_ مثل وسيطات PowerShell المسماة (وخلف الكواليس ، يتم دائمًا تحليلها في البداية على هذا النحو - راجع تعليق BrucePay أدناه) ، ولكن يجب تمريرها كـ -is (باستثناء احتمال توسيع السلسلة) عند استدعاء البرامج الخارجية.

الرموز التي تبدو وكأنها -foo.bar تعاني من نفس المصير (انظر # 6291).

يعمل هذا
يمر echoArgs -foo:bar -foo:bar كوسيطة واحدة
) ، ولكن ليس عند تمرير $Args / دفعه ( @Args ).

ملاحظة: المشكلة أساسية لاستخدام $Args / @Args ، وعلى الرغم من أنها ربما تكون أقل شيوعًا ، إلا أنها تؤثر أيضًا على استخدامها عند استدعاء أوامر PowerShell الأصلية - انظر التعليق أدناه .

خطوات التكاثر

يعمل على نظام macOS أو Linux.

function baz {
  bash -c 'for a; do echo $a; done' - $Args   # note: same with <strong i="32">@Args</strong>
}

baz -foo:bar
'---'
baz -foo.bar

سلوك متوقع

-foo:bar
---
-foo.bar

السلوك الفعلي

-foo:
bar
---
-foo
.bar

تم تقسيم الحجج بشكل غير متوقع إلى قسمين. انظر التعليق المرتبط للخلفية.

بيانات البيئة

PowerShell Core v6.0.1 on macOS 10.13.3
PowerShell Core v6.0.1 on Ubuntu 16.04.3 LTS
PowerShell Core v6.0.1 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Windows PowerShell v5.1.15063.674 on Microsoft Windows 10 Pro (64-bit; v10.0.15063)
Issue-Discussion WG-Language

التعليق الأكثر فائدة

لقد أمضيت الأسبوع الماضي أو نحو ذلك في مصارعة مع هذه القضية. بعد تعقبه إلى قيم معلمات التبديل الإجباري (مثل -foo:$bar ) التي لم يتم ضبطها بعد التبديل باستخدام @Args ، اعتقدت أن هذا يجب أن يكون مشكلة تحديد نطاق غامضة. تخيل دهشتي عندما اكتشفت أن فرض أي قيمة لمعامل التبديل بهذه الطريقة لن يكون له السلوك المتوقع. لقد اختبرته حتى مع إصدار Powershell 7 Preview 1 ولا تزال نفس المشكلة تظهر. أتمنى أن يتم إصلاحها بعد أكثر من عام من كونها مشكلة معروفة ...

كمرجع ، هذا هو الاختبار الذي قمت بإنشائه لإظهار الخطأ. شاهده على جهاز Server 2016 مع Powershell 7 Preview 1 ، بالإضافة إلى جهاز Server 2012 R2 مع Powershell 5.1.

function foo
{
    param(
        [switch]$testArg = $false
    )

    write-host "Test arg value: '$testArg'"
}

function bar
{
    foo <strong i="9">@Args</strong>
}

$testSplat = @{
    testArg = $false
}

write-host "#### Foo tests ####"

foo
foo -testArg:$true
foo -testArg:$false
foo <strong i="10">@testSplat</strong>

write-host "#### Bar tests ####"

bar
bar -testArg:$true
bar -testArg:$false
bar <strong i="11">@testSplat</strong>

ال 3 كومينتر

ملاحظة: الرموز المميزة المعنية ، مثل - foo: bar تبدو مثل وسيطات PowerShell المسماة ،

@ mklement0 كما أصف في التعليقات في # 6292 ، هذه _are_ وسيطات PowerShell المسماة. دائما. يتم ربط المعلمة بعد فترة طويلة من اكتمال التجميع. الآن في AST المترجم ، يحتوي الرمز المميز لـ -foo: على علامة تشير إلى عدم وجود مسافة بعده في الكود المصدري. ينظر NativeCommandParameterBinder إلى عنصر AST هذا لمعرفة ما إذا كان قد تم تعيين العلامة ، ثم يربط المعلمة والوسيطة بدون مسافة بينهما. إذا لم يتم تعيينها ، فسيتم إدخال مسافة. يعمل هذا فقط إذا كانت الوسيطات حرفية (على سبيل المثال ، كان NativeCommandParameter هو الوصول إلى AST للوسيطة). في حالة splatting ، تكون الوسيطات عبارة عن قيم وليست وسيطات حرفية بحيث تحصل على مسافة.

تتمثل إحدى طرق إصلاح ذلك في نشر خاصية الرمز المميز "NoSpace" في بيانات التعريف على قيمة السلسلة المقابلة. يمكن عندئذٍ NativeCommandParameterBinder التحقق من هذه البيانات الوصفية عند تحويل مصفوفة وسيطة إلى سلسلة. ربما يجدر التفكير في هذا الأمر أكثر قليلاً لمعرفة ما إذا كانت هناك حالات أخرى (خاصة * حالات محددة * nix) يجب معالجتها.

يُظهر 6492 (منذ ذلك الحين تم إغلاقه كنسخة) أن الرش @args معطل أيضًا عند استدعاء وظائف PowerShell (وليس البرامج الخارجية فقط):

من المفترض أن يكون دعم هذا السيناريو أكثر صعوبة ، لأن التوقع هنا هو أن المعلمات المسماة يتم تمريرها كما هي ، بأنواعها الأصلية.

إليك نسخة مبسطة:

function b {
  Param
  (
      [Switch] $p1,
      [int] $p2,
      $rest
  )
  "`$p1: [$p1]"
  "`$p2: [$p2]"
  "`$rest: [$rest]"
}

& { b <strong i="9">@args</strong> } -p1:$false 666
$p1: [True]  # `-p1:` was interpreted as just `-p1`
$p2: [0]      # `$false`, as a separate argument, was coerced to [int] 0
$rest: [666] # what was meant to be the 2nd argument was passed as the 3rd

يتمثل الحل البديل - وهو الحل المفضل للبدء به - في تحديد نفس الكتلة param() في وظيفة الترحيل و splat بـ @PSBoundParameters .

لقد أمضيت الأسبوع الماضي أو نحو ذلك في مصارعة مع هذه القضية. بعد تعقبه إلى قيم معلمات التبديل الإجباري (مثل -foo:$bar ) التي لم يتم ضبطها بعد التبديل باستخدام @Args ، اعتقدت أن هذا يجب أن يكون مشكلة تحديد نطاق غامضة. تخيل دهشتي عندما اكتشفت أن فرض أي قيمة لمعامل التبديل بهذه الطريقة لن يكون له السلوك المتوقع. لقد اختبرته حتى مع إصدار Powershell 7 Preview 1 ولا تزال نفس المشكلة تظهر. أتمنى أن يتم إصلاحها بعد أكثر من عام من كونها مشكلة معروفة ...

كمرجع ، هذا هو الاختبار الذي قمت بإنشائه لإظهار الخطأ. شاهده على جهاز Server 2016 مع Powershell 7 Preview 1 ، بالإضافة إلى جهاز Server 2012 R2 مع Powershell 5.1.

function foo
{
    param(
        [switch]$testArg = $false
    )

    write-host "Test arg value: '$testArg'"
}

function bar
{
    foo <strong i="9">@Args</strong>
}

$testSplat = @{
    testArg = $false
}

write-host "#### Foo tests ####"

foo
foo -testArg:$true
foo -testArg:$false
foo <strong i="10">@testSplat</strong>

write-host "#### Bar tests ####"

bar
bar -testArg:$true
bar -testArg:$false
bar <strong i="11">@testSplat</strong>
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات