首页 > 解决方案 > 将 unix 脚本转换为 windows 脚本 - 在 PowerShell 中模拟 Sed 命令

问题描述

我有一个运行良好的 unix 脚本(确切地说是 korn),我需要将其转换为 windows 批处理脚本。到目前为止,我已经尝试在我的代码中插入一个 powershell 命令行,但它不起作用。请帮忙,我对unix脚本和windows脚本都是新手,所以任何帮助都可以。

这是我需要转换的代码行:

#create new file to parse ; exclude past instances of timestamp
    parsefile=/tmp/$$.parse
    sed -e "1,/$TIMESTAMP/d" -e "/$TIMESTAMP/d" $DSTLOGFILE > $parsefile

到目前为止,我已经尝试在我的脚本上调用一个 powershell 命令行,但它没有用:

:set_parse_file
@powershell -Command "Get-Content $SCHLOGFILE | Foreach-Object {$_ -replace('1,/"$TIMESTAMP"/d' '/"$TIMESTAMP"/d'} | Set-Content $PARSEFILE"

请问有什么建议吗?

标签: windowspowershellbatch-file

解决方案


PowerShell没有 sed用于处理行范围类似构造(例如,sed解释1,/foo/为引用从第 1 行到匹配regex foo的后续行的连续行的范围)

使用逐行处理来模拟此功能会更加冗长,但如果将输入文件作为一个整体进行处理,则可以使用相对更简洁的版本- 这只是文件小到足以放入整个内存的选项, 但是(PSv5+ 语法)。

这是纯 PowerShell 代码:

$escapedTimeStamp = [regex]::Escape($TIMESTAMP)
(Get-Content -Raw $SCHLOGFILE) -replace ('(?ms)\A.*?\r?\n.*?' + $escapedTimeStamp + '.*?\r?\n') `
                               -replace ('(?m)^.*?' + $escapedTimeStamp + '.*\r?\n') |
  Set-Content -NoNewline $PARSEFILE

请注意,[regex]::Escape()它用于确保将 的值$TIMESTAMP视为文字,即使它恰好包含正则表达式元字符(字符。对正则表达式引擎具有特殊含义)。
您的ksh代码没有这样做(并且在 中做这件事很重要ksh),所以如果 - 相反 -$TIMESTAMP 应该被解释为正则表达式,只需省略该步骤并$TIMESTAMP直接使用。

-replace运算符基于正则表达式并使用 .NET 正则表达式引擎。

使用Get-Content's -Raw switch需要PSv3+,使用Set-Content's -NoNewlineswitch需要PSv5+。您可以使此命令在早期版本中工作,但需要更多的努力。

cmd.exe从(批处理文件)调用上述内容变得非常笨拙- 你总是必须警惕引用问题 - 但它应该工作:

@powershell.exe -noprofile -command "$escapedTimeStamp = [regex]::Escape('%TIMESTAMP%'); (Get-Content -Raw '%SCHLOGFILE%') -replace ('(?ms)\A.*?\r?\n.*?' + $escapedTimeStamp + '.*?\r?\n') -replace ('(?m)^.*?' + $escapedTimeStamp + '.*\r?\n') | Set-Content -NoNewline '%PARSEFILE%'"

请注意-command参数是如何作为单个"..."字符串传递的,这最终是将代码传递给 PowerShell 的最安全和概念上最简洁的方式。
另请注意,需要像在命令中那样嵌入批处理变量%varname%,并且由于它们包含在'...'上面的嵌入中,因此假设它们的值不包含'字符。

因此,请考虑在 Powershell 中实现整个脚本- 您将拥有更强大的脚本语言供您使用,并且您将避免因连接两个不同的世界而引起的引用难题。


推荐阅读