CMD 输出变量提取子字符串

3

寻求在批处理脚本中对命令输出的变量执行子字符串提取的指导,具体而言,我正在使用的命令是powershell (Get-CimInstance Win32_OperatingSystem).version

我已成功地设置了这个变量,使用for /f "tokens=*" %%i in ('"powershell (Get-CimInstance Win32_OperatingSystem).version"') do set OSvar=%%i

如您所见,我正在查询操作系统版本,并且我有一个未公开的、半有效的用例来使用这个特定的方法来查找它。即使我使用上述方法进行查询的原因可能是错误的,我仍然想要学习如何对此输出执行子字符串提取,以增加我的知识。在给定的上下文中找到解决方案并不那么重要。

显然,这将输出类似于“6.2.9200”,“6.3.9600”或“10.0.XXXXXXX”的结果。我想知道如何提取第二个小数点之前的输出,但是我尝试过的所有尝试都失败了,包括设置分隔符并使用一个等于第一个变量的第二个变量与:~0,3%相等的方法。能否有专家帮忙解决一下?

3个回答

1

好的,按照.进行结果拆分。

@echo off
for /f "tokens=1,2delims=." %%i in ('powershell (Get-CimInstance Win32_OperatingSystem^).version') do (
    set "OSvar=%%i.%%j"
)
echo %OSvar%

或者同一段代码的单行表述:

@echo off
for /f "tokens=1,2delims=." %%i in ('powershell (Get-CimInstance Win32_OperatingSystem^).version') do echo %%i.%%j

你也可以使用标准的 ver 命令;
@for /f "tokens=1-5,*delims=. " %%i in ('ver') do @set OSvar=%%l.%%m

按要求解释。 由于我们通过 . 拆分字符串,每个令牌都可以分配给一个元变量。换句话说,假设它是windows 10.0.18362.959,那么 tokens = 1,2 将把 10 分配给%i ,并将 0 分配给%j


这就是解决方案,谢谢。不知何故,“for /f“tokens=1,2,* delims=.””起作用了,而“tokens=1,2”和“tokens=1,2,3”没起作用。有人能解释一下吗? - Chocobits
它可以与1,2 1,2,3*等一起使用。我更新了答案来证明它:)这是元变量的用法。我们将第一个点值分配给令牌1(元变量%%i),将第二个值分配给令牌2(元变量%%j)。在这里,您不能使用余数,因为我们没有将其分配给令牌。因此,echo %%k将导致%%k`。只有告诉系统之后的所有内容都应分配给另一个令牌,它才能使用它。 - Gerhard
当然,现在使用tokens=1,2是有效的,尽管我发誓以前用过相同的语法。这表明有时候你只需要上网抱怨一下,它就会开始工作了,但还是谢谢你的解释! - Chocobits
玩弄它,设置自己的字符串,并通过使用令牌来查看如何使用各个部分 :) 虽然很高兴你已经解决了。 - Gerhard
如果我有足够的Karma来留下有意义的赞,我会再次为你的答案点赞^^谢谢。 - Chocobits

1
如果你只需要主版本号和次版本号,可以通过来获取,那么只返回这两个数似乎更合理,而不是之后再解析结果。
For /F %%G In ('^""%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" ^
 -NoProfile -NoLogo -Command "[System.Environment]::OSVersion.Version | " ^
 "ForEach-Object { '{0}.{1}' -F $_.Major,$_.Minor }"^"') Do Set "OSVar=%%G"

作为一行代码:
For /F %%G In ('%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoP "[System.Environment]::OSVersion.Version|%%{'{0}.{1}' -F $_.Major,$_.Minor}"')Do Set "OSVar=%%G"

如果您真的想坚持使用Get-CimInstance
For /F %%G In ('^""%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" -NoP ^
 "(Get-CimInstance Win32_OperatingSystem).Version.Split('.')[0,1] -Join '.'"^"'
) Do Set "OSVar=%%G"

作为一行代码:
For /F %%G In ('%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoP "(GCim Win32_OperatingSystem).Version.Split('.')[0,1] -Join '.'"')Do Set "OSVar=%%G"

然而,如果您更喜欢在检索后在do部分解析它,则我建议使用比使用标记和分隔符更简单的方法:

For /F %%G In ('^""%__AppDir__%WindowsPowerShell\v1.0\powershell.exe" ^
 -NoProfile -NoLogo "(Get-CimInstance Win32_OperatingSystem).Version"^"'
) Do Set "OSVar=%%~nG"

作为一行代码:
For /F %%G In ('%__AppDir__%WindowsPowerShell\v1.0\powershell.exe -NoP "(GCim Win32_OperatingSystem).Version"')Do Set "OSVar=%%~nG"

在前两个示例中,.BuildNumber 被视为扩展名,因此可以使用元变量扩展返回没有扩展名的名称。

然而,您不需要 来获取 WMI 信息,您可以使用 替代:

For /F %%G In ('"%__AppDir__%wbem\WMIC.exe" OS Get Version'
) Do If "%%~xG" NEq "" Set "OSVar=%%~nG"

再次作为一行代码:

For /F %%G In ('%__AppDir__%wbem\WMIC.exe OS Get Version')Do If "%%~xG" NEq "" Set "OSVar=%%~nG"

2
OSVersion的问题在于它在Windows 8中已被弃用,并且可能会产生不一致的结果。我曾经看到Windows 8.1(6.3.9600)将自己标识为Windows 8(6.2.9200)。使用CIMInstance调用WinRM是查询此信息的推荐方法。 - Chocobits
据我记得,@JeremyBrown,它在后台使用的方法已经被弃用了,但是该命令仍然按预期正常工作。请尝试一下,我知道它至少在Windows 10上可以工作! - Compo
1
你有点在说“它在一台电脑上运行了,所以它总是能运行”,但我已经展示了OSVersion在Windows 8上有限制的演示。当你要将一个脚本推广到成千上万台机器时,你不能采取“够好”的方法。 - Chocobits
不,我并不是说它总是有效的,这也是为什么我包含了一个使用你特定命令的简化版本的原因!你也可以忘记使用 [tag:powershell],而使用 [tag:wmic],所以我也在我的答案中包含了这种方法。 - Compo
如果我很追求严谨,@JeremyBrown,我会建议我的开头回答是关于从[tag:powershell]检索所需输出,而不是使用OSVersion检索版本。我很追求严谨,所以为了取悦你,我在开头的那个答案下面直接添加了另一个版本,它不使用OSVersion,但仍然返回你想要的字符串,而不是之后解析它。 - Compo
显示剩余5条评论

0
希望这是你想要提取的内容:
@echo off
@For /f "tokens=1,2,3 delims=." %%a in (
    '"powershell (Get-CimInstance Win32_OperatingSystem).version"'
) Do ( 
    Set "FirstVar=%%a"
    Set "SecondVar=%%b"
    Set "ThirdVar=%%c"
    Set "AllVar=%%a.%%b.%%c
)

echo FirstVar  = %FirstVar%
echo SecondVar = %SecondVar%
echo ThirdVar  = %ThirdVar%
echo AllVar    = %AllVar%
pause

这将导致输出为:%a。%b设置令牌和分隔符似乎很棘手,可能是因为它正在将已经有括号的powershell命令的输出作为输入。 - Chocobits
UsebackQ添加到for循环选项中,并将单引号更改为反引号。 - T3RR0R
感谢你们两位迄今为止的建议。我已经尝试了这个:
for /f "Tokens=1,2,3 delims=. USEBACKQ" %%a in (`"powershell (Get-CimInstance Win32_OperatingSystem).version"`) do (set "OSvar1=%%a" set "OSvar2=%%b" set "OSvar3=%%c" set "OSvar=%%a.%%b.%%c") echo %OSvar% 结果是这样的:
%a.%b 即使执行 echo %%a 也会得到 %a 的结果。
- Chocobits
USEBACKQ Tokens=1,2,3 delims=. - T3RR0R
@T3RR0R,这里绝对没有理由使用 usebackq - Gerhard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接