尝试使用 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 然后丢弃,请勿尝试在setlocalendlocal 之间设置 变量,如果您需要稍后的代码来查看这些更改。

【讨论】:

【参考方案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 行连接到批处理变量的主要内容,如果未能解决你的问题,请参考以下文章

Powershell 查看日志并发送电子邮件通知

Invoke PowerShell by UiPath

使用 PowerShell 重命名 zip 以匹配其内容

Powershell企业应用 - 第05章 编写Powershell日志系统

使用 CMD 为文件夹中所有文件的最后修改日期生成日志?

powershell 这将结束当前的SharePoint日志文件并启动一个新的日志文件。非常便利