我使用以下代码从 file1.txt
中删除 file2.txt
中的行。
powershell -Command "$(Get-Content file1.txt) | Where-Object {$_ -notIn $(Get-Content file2.txt)}"
但是我在寻找值表达式时收到有关 -notIn 的错误。但 file2.txt
确实存在且不为空。
导致错误的原因以及如何修复它?
最佳答案
为了执行速度,不要执行
Get-Content file2.txt
在每个循环迭代中 - 预先缓存其结果。为了内存效率,不要收集
file1.txt
的所有行预先使用$(...)
在通过管道发送它们之前。
因此(为了简洁起见,我省略了 powershell -Command "..."
包装器):
$f2 = Get-Content file2.txt; Get-Content file1.txt | Where-Object { $f2 -NotContains $_ }
Which $ are necessary, and why?
<强> (...)
和 $(...)
(子表达式运算符)和 @(...)
(数组子表达式运算符)all将整个命令/命令的输出作为一个整体收集在一个数组中 ( [System.Object[]]
),除非输出仅包含 1 项,其中返回该项本身。
(...)
,它只能包含一个单个命令或表达式,是必需的:
- 澄清表达式中的优先级,
- 使用命令(cmdlet/函数/外部实用程序调用)作为表达式的一部分。
- 在管道中,您可以使用它来强制预先收集所附命令的整个输出,但这样做会抵消管道的内存限制优势。
- 也就是说,使用类似
(Get-Content file) | ... | Set-Content file
的内容允许更新给定文件file
“就地” - 但请注意,这需要file
的全部内容适应内存。
- 也就是说,使用类似
- 除非您有如下所述的其他要求,否则首选
(...)
至$(...)
和@(...)
.
$(...)
只需要:向PetSerAl致敬感谢他的帮助。
包含语句,例如
if
和foreach
包含多个命令/表达式/语句
将上述内容嵌入
"..."
(双引号字符串,其内容可进行插值(扩展))。
在列出的运营商中,$(...)
是唯一可以(直接)嵌入双引号字符串中的一个。$(...)
- 不像(...)
- 如果发生潜在终止错误,不会中止整个命令;例如:-
'hi' + $(1/0)
和"hi$(1/0)"
报告被零除错误,但仍然打印hi
;相比之下,'hi' + (1/0)
不 - 除零错误会中止整个表达式。 - 请注意,无条件终止错误甚至会中止任何
$(...)
- 包含表达式;例如,'hi' + $(Throw 'err')
和"hi$(Throw 'err')"
两者都只打印错误消息,而不打印hi
.
-
@(...)
只需要:
确保命令的输出是一个数组,即使只返回1项;在其他方面,它的作用类似于
$()
,但您不能在"..."
内使用它;详细讨论@()
,参见this answer我的。在 PSv3+ 中,标量和数组的统一处理通常使得
@(...)
然而不必要 - 请参阅 this answer我的。
关于windows - Powershell命令不起作用: removing lines from file1 that are in file2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44608696/