foreach与多变量foreach($number)在Powershell中

chhqkbe1  于 2023-11-18  发布在  Shell
关注(0)|答案(5)|浏览(144)

我想在foreach中使用多个输入,如下所示:

foreach($numberin in [System.IO.File]::ReadLines(".\numberin.txt") & ($numberout in [System.IO.File]::ReadLines(".\numberout.txt")) 
{ ... }

字符串
但不知何故“&”在这里不起作用。
这样

foreach($numberin in [System.IO.File]::ReadLines(".\numberin.txt") -and ($numberout in [System.IO.File]::ReadLines(".\numberout.txt"))


它告诉我“意外的代币”
这样

foreach($numberin in [System.IO.File]::ReadLines(".\numberin.txt") -and ($numberout in [System.IO.File]::ReadLines(".\numberout.txt")


it tells me I need a closing“)”for the foreach
为了阐明我想做什么:我想从两个文件中加载一些输入到两个变量中,并在每次从每个文件中加载新行时对它们执行一些操作。

x7rlezfr

x7rlezfr1#

如果我理解正确的话,get-content接受一个输入文件名数组。它不需要额外的括号。&是调用操作符,-and是条件操作符。

foreach ($numberin in get-content numberin.txt,numberout.txt) { 
  $numberin 
}

字符串
下面是一个使用$( )来合并组合两个命令输出的更一般的示例:

foreach ($i in $(dir; get-date) ) { 
  $i 
}


实际上,&&操作符在powershell 7中工作,只要第一个命令成功。||只会使用第一个文件。

foreach ($i in cat file1 && cat file2 ) { $i }

xdnvmnnf

xdnvmnnf2#

&是Pwsh 7中的调用操作符+&&是一个pipeline chain operator,它指示PowerShell只有在左侧成功时才运行右侧。-and是一个logical operator,从你提供的代码来看,我认为它没有达到你的预期。
如果你试图合并的结果2读操作,你可以考虑简单地阅读他们两个。在Pwsh 7+使用&&操作,可能看起来像这样:

[System.IO.File]::ReadLines( 'C:\temp\test2.csv' ) && [System.IO.File]::ReadLines( 'C:\temp\test2.csv' ) |
ForEach-Object{ $_ }

字符串
在旧版本中,您可以执行以下操作:

{
    [System.IO.File]::ReadLines( 'C:\temp\test2.csv' )
    [System.IO.File]::ReadLines( 'C:\temp\test2.csv' ) 
}.Invoke() |
ForEach-Object{ $_ }


你也可以将文件读取输出发送给1个或多个变量。内存很少是问题,所以你可以将文件读取输出发送给1个或多个变量。这可能会使代码更容易阅读和使用等。
很容易转换为ForEach关键字,而不是ForEach-Object,但我不会说更多,直到意图/期望的结果是明确的。

q9yhzks0

q9yhzks03#

在PowerShell中,使用Get-Content载入档案。

$a = Get-Content .\numberin.txt

字符串
默认情况下,这将在pipeline中发出单独的行。

$a = Get-Content .\numberin.txt

$a | Select-Object -First 1


加载第二个文件。

$a = Get-Content .\numberin.txt
$b = Get-Content .\numberout.txt


您尚未说明如何处理文件数据。
展望未来,没有必要创建自己的算法来比较文件,可以使用Compare-Object
请仔细注意Compare-Object参数,因为这些选项可能会解决您的一些问题。

$a = get-content .\a.out
$b = get-content .\b.out

Compare-Object $a $b

# output 

InputObject                                                 SideIndicator
-----------                                                 -------------
sapien. Quisque ac lectus sit amet lectus ornare mattis.    =>
Etiam ut placerat purus. Aliquam at hendrerit purus, ac     =>
iaculis risus. In hac habitasse platea dictumst. Aenean eu  =>
potenti. Pellentesque felis ligula, dignissim vel neque     <=
commodo, fermentum pharetra neque. Sed placerat a metus nec <=
tincidunt. Sed massa quam, viverra non viverra eget,        <=


请注意,SideIndicator是一个普通的对象属性。它可以在过滤器中使用。

$a = get-content .\a.out
$b = get-content .\b.out

Compare-Object $a $b | Where-Object { $_.SideIndicator -eq "<=" } 

# output 

InputObject                                                 SideIndicator
-----------                                                 -------------
potenti. Pellentesque felis ligula, dignissim vel neque     <=
commodo, fermentum pharetra neque. Sed placerat a metus nec <=
tincidunt. Sed massa quam, viverra non viverra eget,        <=


或者,您也可以将档案附加到内存中。

$a = get-content .\a.out
$b = get-content .\b.out

$a, $b


或将结果保存到光盘。

$a = get-content .\a.out
$b = get-content .\b.out

$a, $b | Set-Content .\c.out


另见

ryevplcw

ryevplcw4#

这就是我想做的

#Begin with first line in "numberout.txt"
$counter = 0

foreach ($numberin in [System.IO.File]::ReadLines(".\numberin.txt")){
$numberout = (Get-Content file.txt)[$counter]
$counter = $counter +1

字符串
也许有人可以告诉我如何将我的“Get-Content”替换为[System.IO.File]。

e1xvtsh3

e1xvtsh35#

PowerShell的foreach语句 * 不 * 支持 * 多个 * 迭代变量。

  • GitHub issue #14732中提出了添加这种支持,但不幸的是被否决了。
    • 如果 * 支持已经实现,你的命令应该是这样的:
# WAS NEVER IMPLEMENTED
foreach($numberin, $numberOut in 
  [System.IO.File]::ReadLines((Convert-Path numberin.txt)),
  [System.IO.File]::ReadLines((Convert-Path numberout.txt))
) { ... }

字符串
最接近的方法是使用.GetEnumerator()方法获取enumerator objects,并在while循环中显式枚举它们:

# Obtain enumerators for both files.
$numberInEnum, $numberOutEnum = 
  [System.IO.File]::ReadLines((Convert-Path numberin.txt)).GetEnumerator(),
  [System.IO.File]::ReadLines((Convert-Path numberout.txt)).GetEnumerator()

# Manually enumerate them with .MoveNext() for as long as one file still 
# has input lines left and obtain the current value (line) via .Current:
while ($numberInEnum.MoveNext(), $numberOutEnum.MoveNext() -contains $true) {
  $numberIn, $numberOut = $numberInEnum.Current, $numberOutEnum.Current
  "[$numberIn] vs. [$numberOut]"  # sample output
}

重要

  • 请注意Convert-Path的使用,它确保将 * 完整路径 * 传递给.NET方法调用,这很重要,因为 *.NET的工作目录通常与PowerShell的 * 不同-请参阅this answer了解背景。

至于你尝试了

  • &是 * cmd.exe的 * 语句分隔符:它允许在一行中放置多个语句; PowerShell的等效项是;
  • PowerShell (Core) 7+现在支持&&||,用于多个语句的 * 条件 * 排序。
  • -and,作为一个 * 逻辑 * 运算符,其工作原理完全不同:它将两个操作数强制为 * 布尔 *(并在过程中消耗它们的输出),并返回一个布尔值:如果两个强制为布尔的操作数都被评估为$true,则返回$true,否则返回$false
  • 这些都不能解决你的问题。

相关问题