【问题标题】:Convert bash script into Windows script将 bash 脚本转换为 Windows 脚本
【发布时间】:2019-10-11 20:56:50
【问题描述】:

我有以下 Unix shell 脚本。我想将其转换为 Windows .bat 文件(我知道我可以使用 Cygwin 而不是将其适应 Windows 环境。但 Cygwin 不适合我)。

我知道我可以在线使用 Windows PowerShell 阅读材料。但我不想花几个小时在线学习基础知识来满足这一一次性要求。请不要因为我懒惰而抨击我。我相信这对其他人也会有所帮助,因为它可以作为将来在线搜索的人的快速指南。

这是脚本:

#!/bin/bash
echo ""
cat $1 | grep -A4 "Device_name"; echo ""
cat $1 | grep -A45 "Device_Oops"; echo ""
cat $1 | grep -A150 "Processes:" | sed '/Radar/q'; echo ""
cat $1 | grep -E '[0-9][0-9]:[0-9][0-9]:[0-9][0-9]' | grep -i -E 'error|restart' 

要回答有关我尝试过的问题,我在运行“find”命令时遇到了问题,该命令相当于本网站grep 中的grephttp://tldp.org/LDP/abs/html/dosbatch.html

这是我的Joy.txt 文件(接下来的两行):

Device_name router@home
testing only

然后在 PowerShell 提示符下我运行了以下命令:

cat Joy.txt | find "Device_name"

我期待看到上述文件的第一行。但相反,我得到参数格式不正确的错误。有人可以帮忙吗?

【问题讨论】:

  • 你有没有尝试过?结果如何?
  • Windows批处理文件和Powershell不一样。批处理文件已经存在了 20 多年,我认为学习它来完成上述操作可能需要一两个小时
  • 你不应该在这里发帖,因为你想教育别人。向我们展示您迄今为止所做的工作,我们会为您提供帮助。

标签: powershell batch-file


【解决方案1】:

findstr(或find)中不存在或多或少直接等效于grep -A,Windows 的本机grep 等效项。但是,PowerShell 中的 Select-String 带有 -Context 参数。

如果我正确理解了您的脚本,则意味着:

  • 写一个空行
  • 写入所有包含“Device_name”的行,然后是四行上下文,然后是一个空行
  • 写入所有包含“Device_Oops”的行,然后是 45 行上下文,然后是一个空行
  • 如果包含“Radar”的所有行也包含“Processes:”或者在包含“Processes:”的行之后的前 150 行内,​​则写入所有包含“Radar”的行
  • 写入所有包含三对数字的行,用冒号分隔,同时包含“错误”或“重新启动”,不区分大小写。

所以它或多或少归结为:

$f = Get-Content $args[0]
function Emulate-Grep {
    begin { $first = $true }
    process {
      if (!$first) { '--' }
      $_.Line
      $_.Context.PostContext
      $first = false
    }
}

Write-Host
$f | Select-String -CaseSensitive -Context 0,4 'Device_name' | Emulate-Grep; Write-Host
$f | Select-String -CaseSensitive -Context 0,45 'Device_Oops' | Emulate-Grep; Write-Host
[string[]]($f | Select-String -CaseSensitive -Context 0,150 'Processes:' | Emulate-Grep) -split "`n" -cmatch 'Radar'; Write-Host
$f -match '\d{2}(:\d{2}){2}' -match 'error|restart'

(未测试)

请注意,由于试图模仿 grep 的输出行为,这有点难看。

如果您只需要匹配行和以下内容,那么我只需编写一个小函数:

function Get-Matching([array]$InputObject, [string]$Pattern, [int]$Context = 0) {
    $n = $InputObject.Length - 1
    0..$n |
      where { $InputObject[$_] -cmatch $Pattern } |   
      foreach { $InputObject[$_..($_+$Context)] }
}

然后在不再那么复杂的脚本中使用它(仍在尝试重新创建一些输出选择,例如空行):

$f = gc $args[0]
Write-Host
Get-Matching $f Device_name 4; Write-Host
Get-Matching $f Device_Oops 45; Write-Host
Get-Matching $f 'Processes:' 150 | ? { $_ -cmatch 'Radar' }; Write-Host
Get-Matching $f '\d{2}(:\d{2}){2}' | ? { $_ -match 'error|restart' }

您还会注意到我删除了 Select-String,这是一个我从未真正理解其用途的 cmdlet(除了提供与 grep/findstr 的紧密匹配,但通常我发现其他方式更灵活) .

【讨论】:

  • 感谢您的意见。但要实现打印匹配行的简单任务,这是一个如此复杂的脚本。 Windows 脚本可以像上面的 bash 脚本一样简单吗?我需要做的就是从输入文件中打印匹配的行(及其后续行)。提前谢谢你。
  • 当然可以。我只是或多或少地假设您想要相同的行为。我更新了答案。
【解决方案2】:

关于Joy.txt,这很简单:

cat .\Joy.txt | Select-String "Device_Name"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 2022-06-15
    • 2016-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多