尝试使用 powershell 将日志文件的最后 10 行连接到批处理变量
Posted
技术标签:
【中文标题】尝试使用 powershell 将日志文件的最后 10 行连接到批处理变量【英文标题】:Trying to concatenate the last 10 lines of a log file to a batch variable using powershell 【发布时间】:2021-12-22 12:44:17 【问题描述】:我是 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%
我使用子字符串的原因是日志文件中的某些行以 开头。我以为这是我唯一的问题,但事实并非如此。如果需要更多信息,请告诉我。谢谢!
【问题讨论】:
您需要保护set命令中的特殊字符。set "LAST_TEN=!LAST_TEN!%%x"
不走运,同样的错误
为什么在 EARTH 上你将 BAT/CMD 与 PoSh 混合在一起?你可以做你在 powershell 中展示的所有东西......那么为什么要混合两者呢?
你试过echo !last_ten!
吗?
顺便说一句:Get-Content download.log -Tail 10
可以 - 无需单独的 Select-Object
调用 - 并且性能更好。此外,没有理由使用 & ...
来调用通过 -command
(-c
) 参数传递给 PowerShell 的 CLI 的代码 - 只需直接使用 ...
。旧版本的 CLI documentation 错误地建议 & ...
是必需的,但这已得到纠正。
【参考方案1】:
注意:您的own answer 显示了有效的解决方案,但我想我会提供一些背景信息。
Squashman 提供了关键指针:
从echo %LAST_TEN%
切换到echo !LAST_TEN!
可以避免变量value 中的元字符(特殊字符,如<
和>
)出现问题,这些问题会导致您的错误消息。
替代方法是双引号变量引用 - 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
。
要在 literal 字符串中转义 !
字符,应该逐字使用,您需要在unquoted 字符串中使用^^!
(原文如此),并且@ 987654346@ 内"..."
。
%...%
变量引用(例如,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
然后丢弃,请勿尝试在setlocal
和endlocal
之间设置 变量,如果您需要稍后的代码来查看这些更改。
【讨论】:
【参考方案2】:既然您已经在使用 PowerShell,为什么不让它完成这项工作呢?
获取最后十行并将它们连接在括号内,例如:
For /F Delims^=^ EOL^= %%G In ('%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "(Get-Content 'download.log' | Select-Object -Last 10) -Join ''"') Do Set "LAST_TEN=%%G"
【讨论】:
【参考方案3】:改变
echo %LAST_TEN%
到
echo !LAST_TEN!
【讨论】:
以上是关于尝试使用 powershell 将日志文件的最后 10 行连接到批处理变量的主要内容,如果未能解决你的问题,请参考以下文章