简体   繁体   English

powershell中的grep gci输出

[英]grep gci output in powershell

I am trying to determine if some environment variables are set (for postgres environment).我试图确定是否设置了一些环境变量(对于 postgres 环境)。 They usually start with PG.他们通常以PG开头。 (Eg PGUSER, PGPASSWORD, etc). (例如 PGUSER、PGPASSWORD 等)。 The following command does output it.以下命令确实输出了它。 (Provided I set it previously). (前提是我之前设置过)。

gci env:* | sort name | more

To eliminate the scrolling I tried the following:为了消除滚动,我尝试了以下操作:

gci env:* | sort name | select-string "PG"

This doesn't return anything.这不会返回任何东西。 What am I doing wrong here?我在这里做错了什么?

Edit: the alternative I have for now:编辑:我现在的替代方案:

gci env:* | sort name  | % { $var = $_.Name + ":" + $_.Value; Write-Output $var } | select-string "PG"

There must be a better alternative.必须有更好的选择。

You're using the wrong mindset.你使用了错误的心态。 Don't try to work with PowerShell like everything is a string.不要尝试使用 PowerShell,就像一切都是字符串一样。 That's Unix-like thinking, and it's going to work as well as driving nails with a screwdiver.这是类 Unix 的想法,它会像用螺丝刀钉钉子一样工作。 You need to switch to object-oriented thinking because in PowerShell you're working with objects 99% of the time.您需要切换到面向对象的思维,因为在 PowerShell 中,您 99% 的时间都在处理对象。

Generally, you would just do this for something as simple as what you're looking for:通常,您只需为您正在寻找的简单内容执行此操作:

Get-ChildItem Env:PG* | Sort-Object -Property Name

If the globbing that Get-ChildItem supports doesn't work, you would want to use Where-Object with the -like operator which is similar globbing to what Get-ChildItem can do:如果Get-ChildItem支持的 globbing 不起作用,您可能希望将Where-Object-like运算符一起使用,这与Get-ChildItem可以执行的操作类似:

Get-ChildItem Env:* | Where-Object Name -like 'PG*' | Sort-Object -Property Name

If you need to search values, you can do it like this:如果您需要搜索值,您可以这样做:

Get-ChildItem Env:* | Where-Object Value -like 'PG*' | Sort-Object -Property Name

And if you want to do both, you'd use the full synax of Where-Object :如果你想同时做这两件事,你可以使用Where-Object的完整语法:

Get-ChildItem Env:* | Where-Object { $_.Name -like 'PG*' -or $_.Value -like 'PG*' } | Sort-Object -Property Name

Or you can use the -match operator, which lets you specify a .Net regular expression:或者您可以使用-match运算符,它可以让您指定一个 .Net 正则表达式:

Get-ChildItem Env:* | Where-Object Name -match '^PG' | Sort-Object -Property Name

Or if you know exactly what you're looking for:或者,如果您确切地知道您在寻找什么:

$Vars = 'PGUSER', 'PGPASSWORD'

Get-ChildItem Env:* | Where-Object Name -in $Vars | Sort-Object -Property Name

Remembering, of course, that PowerShell is usually case-insensitive.当然,请记住,PowerShell 通常不区分大小写。 You can specify -clike , -cmatch , -cin , etc. if you want case-sensitive operators.如果需要区分大小写的运算符,可以指定-clike-cmatch-cin等。

Alternately, you can use the $env: automatic variable namespace.或者,您可以使用$env:自动变量命名空间。

if ($null -eq $env:PGUSER) { 'Not set' }

See also Get-Help about_Environment_Variables .另请参阅Get-Help about_Environment_Variables

Beware that setting environment variables permanently is not exactly self-evident.请注意,永久设置环境变量并不是不言而喻的。 It's described briefly in the above link, but the bottom line is that you have to call [System.Environment]::SetEnvironmentVariable() , which you can find documented here .在上面的链接中对其进行了简要描述,但最重要的是您必须调用[System.Environment]::SetEnvironmentVariable() ,您可以在此处找到记录。 In Windows land, environment variables are basically legacy features with the exception of Windows OS level variables (like PATH) so they're no longer supported like you might expect.在 Windows 领域,除了 Windows 操作系统级别的变量(如 PATH)之外,环境变量基本上是遗留功能,因此不再像您期望的那样支持它们。

Your approach to how this command should work and your instinct that there has to be a better alternative is exactly correct.您对这个命令应该如何工作的方法以及您必须有更好的替代方案的直觉是完全正确的。 This is quite a frustrating issue in my mind and I also asked a variation on this question a few days back.在我看来,这是一个非常令人沮丧的问题,几天前我也问过这个问题的变体。

Select-String only handles strings and what you are passing to it in the above is not a string, so it returns nothing. Select-String只处理字符串,你在上面传递给它的不是字符串,所以它什么都不返回。 Obviously, you might think that since Select-String requires a string, that it would implicitly change it into a string, but no.显然,您可能认为由于Select-String需要一个字符串,它会隐式地将其更改为字符串,但事实并非如此。 So the next thing to consider is to change it to a string, but that creates even more confusion.所以接下来要考虑的是将其更改为字符串,但这会造成更多混乱。

gci env:* | sort name | out-string | select-string "Pro"

So now you just get everything returned.所以现在你只是得到了一切 What's happening here is that out-string returns all lines as a single string, so if there is any hit for "Pro" you get everything returned.这里发生的事情是out-string所有行作为单个out-string返回,因此如果“Pro”有任何命中,您将返回所有内容。

What you need to do is to use out-string -stream which splits the string up by linebreaks so that you get a string per line, and only then do you get rational output.您需要做的是使用out-string -stream通过换行符拆分字符串,以便每行获得一个字符串,然后才能获得合理的输出。

gci env:* | sort name | out-string -stream | select-string "Pro"

More on this here: Using PowerShell sls (Select-String) vs grep vs findstr .更多相关信息: 使用 PowerShell sls (Select-String) vs grep vs findstr The github request linked to in there is trying to change the functionality so that select-string will implicitly have an out-string -stream in the background so that your original command will work.链接到那里的 github 请求试图更改功能,以便select-string在后台隐式有一个out-string -stream ,以便您的原始命令可以工作。

Often we need strings to output results and there is nothing wrong with wanting to manipulate strings (in fact, it depends what you need of course - if you need to do further object manipulations, keep it as an object for that, but if you just need the string output, you should not have to jump through hoops to get that!).通常我们需要字符串来输出结果,想要操作字符串并没有错(事实上,这当然取决于你需要什么——如果你需要做进一步的对象操作,把它作为一个对象,但如果你只是需要字符串输出,你不应该跳过箍来得到它!)。 If you use a string-manipulation tool like select-string then PowerShell should at least convert the incoming information to a string to provide meaningful output.如果您使用像select-string这样的字符串操作工具,那么 PowerShell 至少应该将传入的信息转换为字符串以提供有意义的输出。 Compare with findstr : if you pipe the above to findstr.exe , exactly that will happen and it will implicitly convert with | out-string -streamfindstr比较:如果您将上述内容通过管道传递给findstr.exe ,就会发生这种情况,并且它将隐式转换为| out-string -stream | out-string -stream for findstr (and all other external / non-PowerShell programs) and so gci env:* | findstr "Pro" | out-string -stream用于findstr (以及所有其他外部/非 PowerShell 程序)以及gci env:* | findstr "Pro" gci env:* | findstr "Pro" (on a PowerShell console!) gives you rational output. gci env:* | findstr "Pro" (在 PowerShell 控制台上!)为您提供合理的输出。 select-string is a string-manipulation tool so I find the idea that people are not thinking right about it for expecting a string-manipulation tool to manipulate the incoming information as a string to be unfair on users. select-string是一个字符串操作工具,所以我发现人们没有正确考虑它的想法,因为期望字符串操作工具将传入的信息作为字符串进行操作,这对用户不公平。 PowerShell is an incredibly versatile language but I think this is a common area of confusion. PowerShell 是一种非常通用的语言,但我认为这是一个常见的混淆领域。 Hopefully, future versions of select-string will operate in the above fashion as a result of the change request on GitHub, but in the meantime, just use | out-string -stream希望未来版本的select-string能够根据 GitHub 上的更改请求以上述方式运行,但与此同时,只需使用| out-string -stream | out-string -stream and it will all work as expected, including for other string manipulations which you can then deal with easily: | out-string -stream它将按预期工作,包括其他字符串操作,您可以轻松处理这些操作:

(gci env:* | sort name | out-string -stream) -replace "Pro", "XXX" | select-String "XXX"

to keep this short: Your approach doesn't work in PowerShell.保持简短:您的方法在 PowerShell 中不起作用。 All you need to do is你需要做的就是

# Short Version
gci env: | ? Name -match "PG" | sort Name

# Long Version
Get-ChildItem -Path env: |
Where-Object -FilterScript { $_.Name -match "PG" } |
Sort-Object -Property Name

Select-String works fine with string content piped one by one instead of a big stream. Select-String可以很好地处理字符串内容,而不是一个大流。

Cheers干杯

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM