根据 grep 输出有条件地运行一个块

根据 grep 输出有条件地运行一个块

我找到了许多解决这个问题的办法,但是不幸的是,它们似乎都不适用于我的 Windows 系统。

我正在FOR批处理文件中运行一个循环来循环遍历多个文本文件。对于每个文本文件,ECHO如果 (来自 WinGNU) 返回一行,我希望得到它的名称(并可能将输出重定向到文件)grep。快速的谷歌搜索告诉我这样做:

IF grep -c pattern file ( stuff )

但这会引发错误

-c was unexpected at this time.

grep --quiet或者,我认为我可以使用如下退出代码:

grep -q pattern file
IF ERRORLEVEL 1 ( stuff )

即使 grep 成功,这也总是会导致 IF 测试失败。

如果我的 grep 找到匹配项,是否有一个好的方法可以在 Windows 中运行条件语句?

我的代码是:

SET locations=( a, long, list, of, last, two, octets )
SETLOCAL ENABLEDELAYEDEXPANSION

FOR %%r IN %locations% DO (
    grep -i "^\[CardSwipe\]" \\10.0.%%r\path\to\file.ini
    IF ERRORLEVEL 1 echo %%r

我的输出是:

[this line left intentionally blank] :)

答案1

我想不出用 Batch 来做这件事的好方法,尤其是因为你引入了我不熟悉的非本机命令行工具。不过,PowerShell 通常更适合这样的任务。

这应该可以在 PowerShell 中为您完成这项工作:

$Hosts = @('1.1','1.2','101.243','54.28')
$Hosts | ForEach-Object {
    if ((Get-Content "\\10.0.$_\path\to\file.ini" | Select-String "^\[CardSwipe\]").length -ne 0) {
        Write-Output $_}}

具体细节如下:

  1. 我们将$Hosts其定义为一个数组,其中包含表示要检查的每个系统的最后两个八位字节的字符串。另一种设置方法是使用一个文本文件,每行一个条目。
  2. 然后我们将数组导入其中ForEach-Object,顾名思义,它将对数组中的每个对象执行命令。如果您使用文本文件作为列表,则需要使用 来获取它,Get-Content然后将其导入ForEach-Object其中代替变量。
  3. 条件中的脚本if将为您进行搜索。
  4. Get-Content按照其说明进行操作 - 获取内容。
  5. "\\10.0.$_\path\to\file.ini"是我们给出的目标Get-Content。通过将字符串括在双引号中,我们告诉 PowerShell 我们希望它在传递参数之前扩展字符串中的变量。$_是一个内置变量,它引用正在处理的对象,例如ForEach-Object
  6. 的输出通过Get-Content管道传输到Select-StringSelect-String对于 PowerShell 来说或多或少是 grep - 事实上,我有点惊讶这个没有内置别名,因为其他 cmdlet(他们称之为 PowerShell 命令)有类似 *nix 命令的别名,如 ls 和 wget。
  7. "^\[CardSwipe\]"- 哦,是的。Select-String顺便说一下,采用 RegEx。
  8. 将命令括在括号中允许您直接检索它们生成的对象的属性,而不必先将它们转储到变量或其他东西中。所以,这( ... ).length意味着我想要获取括号内脚本输出的任何对象的长度。对于字符串,这是基本字符长度。对于数组,这是数组中成员的数量。当检索文本文件或类似对象时,它将作为“字符串数组”返回。因此,对象的长度属性值将等于文本中的行数。
  9. -ne是“不等于”的比较运算符。如果Select-String未找到任何匹配项,则其输出将是一个长度为零的空数组。其他任何内容的长度都将为 1 或更大,因此我们触发ifon -ne 0
  10. Write-Output是另一个不言自明的命令。它写入输出。在本例中,我们告诉它我们想要输出当前正在处理的对象ForEach-Object。当然,由于这是在if块内,因此只有当 ini 文件符合给定条件时才会发生这种情况。输出将是发生这种情况时正在处理的“最后两个八位字节”。

相关内容