在 powershell 中,我想通过一个文本文件进行两次 Ioop,但在第二个循环中我想从第一个循环的末尾继续
In powershell, i want Ioop twice through a text file but in second loop i want to continue from end of first loop
我有一个文本文件要处理。文本文件有一些配置数据和一些网络命令。我想 运行 所有这些网络命令并重定向某些日志文件中的输出。
在文本文件的开头,有一些配置信息,如文件名和文件位置。这可用于命名日志文件和日志文件的位置。这些行以一些特殊字符开头,例如“<#:”。只是要知道该行的其余部分是关于文件的配置数据而不是要执行的命令。
现在,在我开始执行网络命令(以一些特殊字符如 '<:' 开头)之前,首先我想读取有关文件的所有配置信息,即文件名、位置、覆盖标志等。然后我可以运行 所有命令并将输出转储到日志文件中。
我使用 get-content 迭代器遍历整个文本文件。
问题:有什么方法可以从特定行再次开始循环遍历文件?
这样我就可以首先处理配置信息(循环直到我第一次遇到要执行的命令,记住这个行号),创建日志文件然后保留 运行ning 命令并将输出重定向到日志文件(从最后记住的行号开始循环).
配置文件如下所示:
<#Result_File_Name:dump1.txt
<#Result_File_Location:C:\powershell
<:ping www.google.com
<:ipconfig
<:traceroute www.google.com
<:netsh interface ip show config
我的 powerhsell 脚本如下所示:
$content = Get-Content C:\powershell\config.txt
foreach ($line in $content)
{
if($line.StartsWith("<#Result_File_Name:")) #every time i am doing this, even for command line
{
$result_file_arr = $line.split(":")
$result_file_name = $result_file_arr[1]
Write-Host $result_file_name
}
#if($line.StartsWith("<#Result_File_Location:"))#every time i am doing this, even for command line
#{
# $result_file_arr = $line.split(":")
# $result_file_name = $result_file_arr[1]
#}
if( $conf_read_over =1)
{
break;
}
if ($line.StartsWith("<:")) #In this if block, i need to run all commands
{
$items = $line.split("<:")
#$items[0]
#invoke-expression $items[2] > $result_file_name
invoke-expression $items[2] > $result_file_name
}
}
如果所有的配置信息都以<#
开头,那么先单独处理一下。完成后,您可以假设其余的都是命令吗?
# Collect config lines and process
$config = $content | Where-Object{$_.StartsWith('<#')} | ForEach-Object{
$_.Trim("<#") -replace "\","\" -replace "^(.*?):(.*)" , ' = '
} | ConvertFrom-StringData
# Process all the lines that are command lines.
$content | Where-Object{!$_.StartsWith('<#') -and ![string]::IsNullOrEmpty($_)} | ForEach-Object{
Invoke-Expression $_.trimstart("<:")
}
我对配置部分有点过头了。我所做的是将其转换为 hashtable
。现在您将拥有您的配置选项,就像它们在文件中一样,可以作为对象访问。
$config
Name Value
---- -----
Result_File_Name dump1.txt
Result_File_Location C:\powershell
对您的代码进行少量重新配置,缺少一些部分,如下所示。您很可能需要根据自己的需要进行调整。
# Collect config lines and process
$config = ($content | Where-Object{$_.StartsWith('<#')} | ForEach-Object{
$_.Trim("<#") -replace "\","\" -replace "^(.*?):(.*)" , ' = '
} | Out-String) | ConvertFrom-StringData
# Process all the lines that are command lines.
$content | Where-Object{!$_.StartsWith('<#') -and ![string]::IsNullOrEmpty($_)} | ForEach-Object{
Invoke-Expression $_.trimstart("<:") | Add-Content -Path $config.Result_File_Name
}
根据您的评论,您仍然对重启循环逻辑感到好奇,这是您最初问题的一部分。我会将其添加为对此的单独回答。我仍然更喜欢我的其他方法。
# Use a flag to determine if we have already restarted. Assume False
$restarted = $false
$restartIndexPoint = 4
$restartIndex = 2
for($contentIndex = 0; $contentIndex -lt $content.Length; $contentIndex++){
Write-Host ("Line#{0} : {1}" -f $contentIndex, $content[$contentIndex])
# Check to see if we are on the $restartIndexPoint for the first time
if(!$restarted -and $contentIndex -eq $restartIndexPoint){
# Set the flag so this does not get repeated.
$restarted = $true
# Reset the index to repeat some steps over again.
$contentIndex = $restartIndex
}
}
请记住,当您设置数字时,数组索引是基于 0 的。例如,第 20 行是字符串数组中的第 19 个元素。
在循环内我们运行检查。如果通过,我们将当前索引更改为更早的索引。 write-host
将只打印行,因此您可以看到 "restart" 部分。我们需要设置一个标志,这样我们就不会 运行 陷入无限循环。
我有一个文本文件要处理。文本文件有一些配置数据和一些网络命令。我想 运行 所有这些网络命令并重定向某些日志文件中的输出。
在文本文件的开头,有一些配置信息,如文件名和文件位置。这可用于命名日志文件和日志文件的位置。这些行以一些特殊字符开头,例如“<#:”。只是要知道该行的其余部分是关于文件的配置数据而不是要执行的命令。
现在,在我开始执行网络命令(以一些特殊字符如 '<:' 开头)之前,首先我想读取有关文件的所有配置信息,即文件名、位置、覆盖标志等。然后我可以运行 所有命令并将输出转储到日志文件中。
我使用 get-content 迭代器遍历整个文本文件。
问题:有什么方法可以从特定行再次开始循环遍历文件?
这样我就可以首先处理配置信息(循环直到我第一次遇到要执行的命令,记住这个行号),创建日志文件然后保留 运行ning 命令并将输出重定向到日志文件(从最后记住的行号开始循环).
配置文件如下所示:
<#Result_File_Name:dump1.txt
<#Result_File_Location:C:\powershell
<:ping www.google.com
<:ipconfig
<:traceroute www.google.com
<:netsh interface ip show config
我的 powerhsell 脚本如下所示:
$content = Get-Content C:\powershell\config.txt
foreach ($line in $content)
{
if($line.StartsWith("<#Result_File_Name:")) #every time i am doing this, even for command line
{
$result_file_arr = $line.split(":")
$result_file_name = $result_file_arr[1]
Write-Host $result_file_name
}
#if($line.StartsWith("<#Result_File_Location:"))#every time i am doing this, even for command line
#{
# $result_file_arr = $line.split(":")
# $result_file_name = $result_file_arr[1]
#}
if( $conf_read_over =1)
{
break;
}
if ($line.StartsWith("<:")) #In this if block, i need to run all commands
{
$items = $line.split("<:")
#$items[0]
#invoke-expression $items[2] > $result_file_name
invoke-expression $items[2] > $result_file_name
}
}
如果所有的配置信息都以<#
开头,那么先单独处理一下。完成后,您可以假设其余的都是命令吗?
# Collect config lines and process
$config = $content | Where-Object{$_.StartsWith('<#')} | ForEach-Object{
$_.Trim("<#") -replace "\","\" -replace "^(.*?):(.*)" , ' = '
} | ConvertFrom-StringData
# Process all the lines that are command lines.
$content | Where-Object{!$_.StartsWith('<#') -and ![string]::IsNullOrEmpty($_)} | ForEach-Object{
Invoke-Expression $_.trimstart("<:")
}
我对配置部分有点过头了。我所做的是将其转换为 hashtable
。现在您将拥有您的配置选项,就像它们在文件中一样,可以作为对象访问。
$config
Name Value
---- -----
Result_File_Name dump1.txt
Result_File_Location C:\powershell
对您的代码进行少量重新配置,缺少一些部分,如下所示。您很可能需要根据自己的需要进行调整。
# Collect config lines and process
$config = ($content | Where-Object{$_.StartsWith('<#')} | ForEach-Object{
$_.Trim("<#") -replace "\","\" -replace "^(.*?):(.*)" , ' = '
} | Out-String) | ConvertFrom-StringData
# Process all the lines that are command lines.
$content | Where-Object{!$_.StartsWith('<#') -and ![string]::IsNullOrEmpty($_)} | ForEach-Object{
Invoke-Expression $_.trimstart("<:") | Add-Content -Path $config.Result_File_Name
}
根据您的评论,您仍然对重启循环逻辑感到好奇,这是您最初问题的一部分。我会将其添加为对此的单独回答。我仍然更喜欢我的其他方法。
# Use a flag to determine if we have already restarted. Assume False
$restarted = $false
$restartIndexPoint = 4
$restartIndex = 2
for($contentIndex = 0; $contentIndex -lt $content.Length; $contentIndex++){
Write-Host ("Line#{0} : {1}" -f $contentIndex, $content[$contentIndex])
# Check to see if we are on the $restartIndexPoint for the first time
if(!$restarted -and $contentIndex -eq $restartIndexPoint){
# Set the flag so this does not get repeated.
$restarted = $true
# Reset the index to repeat some steps over again.
$contentIndex = $restartIndex
}
}
请记住,当您设置数字时,数组索引是基于 0 的。例如,第 20 行是字符串数组中的第 19 个元素。
在循环内我们运行检查。如果通过,我们将当前索引更改为更早的索引。 write-host
将只打印行,因此您可以看到 "restart" 部分。我们需要设置一个标志,这样我们就不会 运行 陷入无限循环。