尝试使用 powershell 将日志文件的最后 10 行连接到批处理变量



我是Windows脚本的新手,但在bash和python方面有很多经验。

这就是问题所在。每当我运行它时(这是我迄今为止得到的最好的结果),它都会使它大部分时间都通过,然后出现"文件名、目录名称或卷标语法不正确"的错误。

忽略为换行符设计的代码,我也在为此而战。

setlocal EnableDelayedExpansion
set LF=^

set LAST_TEN=Here are the last 10 lines of the download log:
for /f "tokens=* usebackq" %%x in (`powershell -command "& {Get-Content download.log | Select-Object -last 10 | ForEach-Object {$_.substring(2)}}"`) do (

set LAST_TEN=!LAST_TEN!%%x


)
echo %LAST_TEN%

我采用子字符串的原因是日志文件中的某些行以<和>开头。我以为这是我唯一的问题,但事实并非如此。如果需要更多信息,请告诉我。谢谢!

注意:您自己的答案显示了有效的解决方案,但我想我会提供一些背景信息。

Squashman提供了关键的指示:

  • echo %LAST_TEN%切换到echo !LAST_TEN!可避免变量中的元字符(特殊字符,如<>)出现问题,这些问题是导致错误消息的原因。

  • 另一种方法是双引号变量引用 -echo "%LAST_TEN%"- 但遗憾的是,双引号随后包含在输出中

换句话说:如果您需要echo(可能)包含不带引号的元字符的变量的值

  • setlocal EnableDelayedExpansion放在批处理文件的开头。

  • 然后将感兴趣的变量引用为!VAR!而不是%VAR%:这导致的延迟扩展会阻止该值成为cmd.exe解析的源代码行的一部分(由于%VAR%发生的宏式前期扩展)。

    • 顺便说一句:循环变量 - 例如代码中的%%x- 尽管使用%而不是!作为分隔符,但必须始终以延迟方式扩展,这就是为什么即使没有双引号,set LAST_TEN=!LAST_TEN!%%x工作,这通常是包含元字符的非延迟变量引用的文字和值所需的变量名称和值(例如
      set "LAST_TEN=a < b")

一个简化的示例:

@echo off
setlocal enableDelayedExpansion
:: Define a sample variable
:: Note the "..." enclosing both the name and the value.
set "var=a value with metacharacters: < > & |"
:: Thanks to using !var!, echoing the value *unquoted* works
echo !var!

范围setlocal enableDelayedExpansion

延迟扩展的一个缺陷是,所有!字符被视为延迟变量引用的一部分,通常会导致它们安静地删除;例如,echo hi!输出刚好hi。 要转义应逐字使用的文字字符串中的!字符,您需要在不带引号的字符串中^^!(原文如此),并在"..."^!

%...%变量引用(例如,echo %var:!=^^!%)也需要转义,但对于!...!变量引用,再次避免转义。

为避免此类逃避头痛,您可以按需为给定的行或行块启用setlocal enableDelayedExpansion,并使用endlocal再次禁用它:

@echo off
:: Define a sample variable
:: Note the "..." enclosing both the name and the value.
set "var=a value with metacharacters: < > & |"
:: Because setlocal enableDelayedExpansion is NOT (yet)
:: in effect, the use of "!" is not a problem.
echo hi!
:: Localize the use of delayed expansion
setlocal enableDelayedExpansion
echo !var!
endlocal
:: Use of "!" is again fine.
echo hi again!

警告:由于setlocal会创建环境变量的副本,然后endlocal丢弃副本,因此,如果需要稍后的代码来查看这些更改,请不要尝试在setlocalendlocal之间设置变量。

既然你已经在使用PowerShell,为什么不让它做驴子的工作呢?

抓住最后十行并将它们连接在括号内,例如:

For /F Delims^=^ EOL^= %%G In ('%SystemRoot%System32WindowsPowerShellv1.0powershell.exe -NoProfile -Command "(Get-Content 'download.log' | Select-Object -Last 10) -Join ''"') Do Set "LAST_TEN=%%G"

已更改

echo %LAST_TEN%

echo !LAST_TEN!

最新更新