首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于Linux命令grep -A的Windows等效项(在搜索字符串后返回行)

用于Linux命令grep -A的Windows等效项(在搜索字符串后返回行)
EN

Stack Overflow用户
提问于 2017-07-11 18:27:35
回答 4查看 2.7K关注 0票数 2

我在文本文件中有以下数据,我想获取特定"Node name“的Hostname:

代码语言:javascript
复制
Node 1 entry:

 Node name                      = NODE1
 Comment                        =
 Directory entry type           = LOCAL
 Protocol                       = TCPIP
 Hostname                       = 192.168.100.1

Node 2 entry:

 Node name                      = NODE2
 Comment                        =
 Directory entry type           = LOCAL
 Protocol                       = TCPIP
 Hostname                       = 192.168.100.2

Node 3 entry:

 Node name                      = NODE3
 Comment                        =
 Directory entry type           = LOCAL
 Protocol                       = TCPIP
 Hostname                       = 192.168.100.3 

示例:作为输入,我输入“节点名”,例如NODE2。然后我需要在NODE2下面搜索4行,并读取主机名为192.168.100.2。包含IP地址的行是我想要的结果。

在Linux上,这很简单:

代码语言:javascript
复制
grep -A 4 "NODE3" file.txt | grep Hostname

注意:-A 4用于与搜索匹配的返回行和额外的4行

或者更好:

代码语言:javascript
复制
grep -A 4 "\<NODE3\>" file.txt | grep Hostname

如果NODE3是名称的子字符串,如: NODE3A,则上述命令将仅严格搜索"NODE3“。

或者仅获取IP地址(第三列是列之间用一个或多个空格分隔):

代码语言:javascript
复制
grep -A 4 "\<NODE3\>" file.txt | grep Hostname | gawk '{print $3}'

问:如何在Windows上使用Windows原生命令做同样的事情?

附注:此脚本将在多个Windows计算机上运行,我不想在Windows上安装额外的软件。我知道我可以安装grep和其他命令,但我不想这样做。解决方案必须使用Windows唯一的命令(Windows 7,Windows 2008和更新的应该是工作),因为脚本文件(批处理文件)将运行在几个不同的Windows版本,我不被允许安装软件,也不想分发其他额外的软件。

EN

回答 4

Stack Overflow用户

发布于 2017-07-11 18:57:12

尝尝这个

代码语言:javascript
复制
@echo off

set "skip="
set "host="
set "searchNode=NODE2"

for /F "tokens=1,* delims=[]" %%A in ('type file.txt ^| find /I /N "%searchNode%"') do (
  if not defined skip set/a skip=%%A & goto :found
)
:found
if not defined skip echo/%searchNode% was not found. & exit/B

rem lines_to_skip = line_found + lines_below - 1
set /a skip+=3 
for /F "skip=%skip% tokens=1,* delims=[]" %%A in ('type file.txt ^| find /N /V "^"') do (
  for /F "tokens=1,* delims== " %%a in ("%%B") do set "host=%%b" & goto :stop
)
:stop
echo/%host%
exit/B

首先,搜索文件,直到匹配到所需的字符串,并存储行号。然后,计算要跳过的行(我们搜索第四行,行号+4- 1)。最后,重新解析文件,只读取所需的行。

票数 1
EN

Stack Overflow用户

发布于 2017-07-11 19:17:00

编辑进行了一些简化(去掉了一个If)

代码语言:javascript
复制
@Echo off&SetLocal EnableExtensions EnableDelayedExpansion
Rem pass Node name as Arg1 to this batch
Set "Node=" & Set "IP=not found"
For /F "tokens=1-3delims=:= " %%A in ('type file.txt') Do (
  If /i "%%A%%B" Equ "Nodename" Set "Node=%%C"
  IF /i "%%A%~1" Equ "Hostname!Node!" Set "IP=%%B"
)
Echo IP for Node %1 is %IP%

样本输出

代码语言:javascript
复制
> SO_45031925.cmd Node2
IP for Node Node2 is 192.168.100.2

> SO_45031925.cmd Node1
IP for Node Node1 is 192.168.100.1

> SO_45031925.cmd Node3
IP for Node Node3 is 192.168.100.3

> SO_45031925.cmd Node4
IP for Node Node4 is not found

附注:

在windows中使用grep和gawk时,只有单引号必须与双引号交换:

代码语言:javascript
复制
> grep -A 4 "\<NODE3\>" file.txt | grep Hostname | gawk "{print $3}"
192.168.100.3

此PowerShell变体要求选择字符串仅出现在较新的Windows版本中。

代码语言:javascript
复制
$Node = 'Node3'
$IP = Select-String -Path .\file.txt -Pattern "Node name\s+= $Node" -Context 0,4 |
    ForEach-Object {($_.Context.PostContext[3]).Split('=')[1].Trim()}
"IP for Node {0} is {1}" -f $Node,$IP
票数 1
EN

Stack Overflow用户

发布于 2017-07-12 03:03:32

设计SETX command的目的是在cmd.exe环境中定义持久变量。但是,此命令具有一个不寻常且实际上未使用的功能,该功能允许从文本文件中提取位于其他项目相对位置的项目。最终效果类似于将FOR命令与FINDSTR命令相结合,但具有更多功能,并且以一种更简单的方式。

您希望在示例中获得的结果可以通过以下方式获得:

代码语言:javascript
复制
setx /F test.txt dummyVar /R 4,-1 NODE2

在前一行中,/F test.txt部分指定要搜索的文件,dummyVar是要设置的持久变量。/R 4,-1 NODE2部分的意思是:“执行NODE2项目的/Relative搜索,找到后,返回位于下面4行和之前1项的项目”。"items“从零开始编号,默认以空格分隔,但您可以通过/D开关定义一系列分隔符(类似于for命令的"delims=”开关)。结果是这样展示的:

代码语言:javascript
复制
Extracted value: 192.168.100.2.

因此,为了获得您想要的结果,您必须使用以下代码:

代码语言:javascript
复制
for /F "tokens=3" %%a in ('setx /F test.txt dummyVar /R 4^,-1 NODE2') do set "host=%%a" & goto continue
:continue
set "host=%host:~0,-1%"
echo %host%

请注意,/R 4,-1部分中的逗号必须使用插入符号进行转义,并且结果在结尾处包含一个必须删除的附加点。

这种方法的一个小缺点是,dummyVar是在cmd.exe环境中永久定义的,但这一点不会以任何方式影响cmd.exe操作。

已在Windows XP和8.1上测试。这个管理在this site上有完整的描述。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45031925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档