无法在批处理脚本中连接2个变量的值

时间:2018-05-21 11:48:54

标签: json batch-file

我创建了一个批处理文件,该文件读取包含npm包及其版本的.json文件。

现在一切正常,除了在写入文件

之前连接2个变量中的值

这是InstallPackage.json文件:

{
  "dependencies": {
    "@types/react": "16.3.10",
    "react": "16.3.2",
    "react-dom": "16.3.2",
    "react-scripts": "1.1.4"
  },
  "devdependencies":{}
}

这是批处理文件:

<# : batch portion (contained within a PowerShell multi-line comment)
@echo off & setlocal
setlocal EnableDelayedExpansion
set LF=^


set JSON=
for /f "delims=" %%x in (InstallPackage.json) do (
    set "JSON=!JSON!%%x!LF!"
)

rem # re-eval self with PowerShell and capture results
for /f "delims=" %%I in ('powershell "iex (${%~f0} | out-string)"') do set "%%~I"

rem # output captured results
set JSON[

rem # end main runtime
goto :EOF

: end batch / begin PowerShell hybrid code #>

add-type -AssemblyName System.Web.Extensions
$JSON = new-object Web.Script.Serialization.JavaScriptSerializer
$obj = $JSON.DeserializeObject($env:JSON)

# output object in key=value format to be captured by Batch "for /f" loop
foreach ($key in $obj.keys) { 
    foreach($package in $obj[$key].keys){

###     error happens here ###

        echo $package@$obj[$key][$package] >> packages.txt
    }
}

而不是

@types/react@16.3.10

我明白了:

@types/react@System.Collections.Generic.Dictionary`2[System.String,System.Object][dependencies][@types/react]

这是一个简单的连接,不知道它为什么不起作用。

2 个答案:

答案 0 :(得分:1)

您的PowerShell输出行不是PowerShell-ese。它有点像PowerCmd。取代

echo $package@$obj[$key][$package] >> packages.txt

"JSON[{0:d}]={1}@{2}" -f $i++, $package, $obj[$key][$package] >> packages.txt

...如果要在PowerShell退出批处理环境时填充JSON []数组,或者

"{0}@{1}" -f $package, $obj[$key][$package] >> packages.txt

...如果您只想将连接的值发送到packages.txt。如果是这种情况,请在批处理中删除for /F循环。您还可以在PowerShell中使用gc来读取JSON,这比尝试使用多行值填充Batch变量要优雅得多。

<# : batch portion (contained within a PowerShell multi-line comment)
@echo off & setlocal

set "JSON=InstallPackage.json"

rem # re-eval self with PowerShell and capture results
powershell -noprofile "iex (${%~f0} | out-string)"

rem # end main runtime
goto :EOF

: end batch / begin PowerShell hybrid code #>

add-type -AssemblyName System.Web.Extensions
$JSON = new-object Web.Script.Serialization.JavaScriptSerializer
$obj = $JSON.DeserializeObject((gc $env:JSON))

# output object in key@value format to packages.txt
foreach ($key in $obj.keys) { 
    foreach($package in $obj[$key].keys){
        "{0}@{1}" -f $package, $obj[$key][$package] >> packages.txt
    }
}

我还有一个推荐。如果使用out-file cmdlet,您的意图将更清晰,而不是使用追加重定向编写packages.txt。您是否希望在每次运行时从头开始创建packages.txt?或者,packages.txt会在多次运行中继续增长吗?如果你从现在起一年后重新访问这段代码,你会记得你的意图吗?

这会更清楚:

# output object in key@value format to packages.txt
&{
    foreach ($key in $obj.keys) { 
        foreach($package in $obj[$key].keys){
            "{0}@{1}" -f $package, $obj[$key][$package]
        }
    }
} | out-file packages.txt

如果您打算通过连续运行来增加packages.txt,请使用

out-file packages.txt -append

请参阅?这样,packages.txt将在每次运行时显式覆盖或附加,并且不需要检查文件是否已存在或期望文件不存在。这种方式不那么模糊。

答案 1 :(得分:0)

这么简单的东西需要很多代码。至少对于Xidel

xidel -s InstallPackage.json -e "let $a:=$json/dependencies return $a() ! join((.,$a(.)),'@')" >> packages.txt

' package.txt ':

@types/react@16.3.10
react@16.3.2
react-dom@16.3.2
react-scripts@1.1.4