اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
دو دقیقه
خیلی از ابزارهای command line، براساس فلسفهی bash تهیه شدهاند؛ به این معنا که امکان استفادهی مستقیم از bash، درون دستورات وجود دارد. به عنوان مثال فرض کنید میخواهیم لیست branchهای یک مخزن گیت را با کمک دستور زیر در خروجی، به صورت JSON نمایش دهیم. برای اینکار با یک جستجو شاید به این نتیجه برسید که از پرچم format در دستور git branch استفاده کنید:
در اینجا به گیت گفتهایم که یک فرمت سفارشی، برای خروجی در نظر بگیرد. میخواهیم خروجی، لیستی از آبجکتهایی باشد که شامل یک پراپرتی name با مقدار نام branch هستند. برای مقدار این پراپرتی، از یک placeholder مشخص استفاده شدهاست:
refname در اینجا به نام کامل branch اشاره میکند؛ با این تفاوت که رشتهی refs/heads که در ابتدای آن وجود دارد، برای حذف آن از lstrip=2 استفاده کردهایم. در نهایت این چنین خروجیایی برایمان نمایش داده خواهد شد:
اما فرض کنید میخواهیم یک پراپرتی دیگر نیز با عنوان isMainBranch به این آبجکت اضافه کنیم. برای اینکار معمولاً از یک عبارت bash استفاده میشود: (با فرض اینکه main برنچ اصلیمان است)
اما اگر این دستور را در PowerShell وارد کنید، با خطای زیر مواجه خواهید شد:
زیرا در اینجا از سینتکس bash، برای بررسی شرط استفاده کردهایم. پارزر PowerShell هم بلافاصله بعد از دیدن $، انتظار دارد که بعد از if، از پرانتز استفاده کنیم. احتمالاً فکر میکنید که با escape کردن کاراکتر $، مشکل رفع میشود:
اما در اینحالت همه چیز به عنوان string در نظر گرفته میشود و هیچ ارزیابی برای اجرای nested script رخ نمیدهد؛ در نتیجه خروجی اینچنین خواهد بود:
برای رفع این مشکل باید به صورت کامل از PowerShell استفاده کنیم و JSON موردنظرمان را خودمان تهیه کنیم؛ یعنی بدون استفاده از format در گیت:
PS /> git branch --format='{"name":"%(refname:lstrip=2)"}' --list
%(refname:lstrip=2)
{"name":"main"} {"name":"feature-branch-a"} {"name":"feature-branch-b"} ,...
PS /> git branch --format='{"name":"%(refname:lstrip=2)","isMainBranch":'"$(if [[ $(git symbolic-ref --short HEAD) == "main" ]]; then echo true; else echo false; fi)"' }' --list
ParserError: Line | 1 | … --format='{"name":"%(refname:lstrip=2)","isMainBranch":'"$(if [[ $(gi … | ~ | Missing '(' after 'if' in if statement.
'"`$(if [[ `$
{"name":"main","isMainBranch":$(if [[ $(git symbolic-ref --short HEAD) == main ]]; then echo true; else echo false; fi) } {"name":"feature-branch-a","isMainBranch":$(if [[ $(git symbolic-ref --short HEAD) == main ]]; then echo true; else echo false; fi) } {"name":"feature-branch-b","isMainBranch":$(if [[ $(git symbolic-ref --short HEAD) == main ]]; then echo true; else echo false; fi) }
$branches = git branch | ForEach-Object { $default = $false $activeBranch = git symbolic-ref --short HEAD $currentBranch = ($_.Replace("* ", " ")).Trim() if ($currentBranch -eq $activeBranch) { $default = $true } @{ name = $currentBranch isMainBranch = $default } | ConvertTo-Json } | ConvertFrom-Json