Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl Powershell主机文件编辑_Perl_Powershell_Host - Fatal编程技术网

Perl Powershell主机文件编辑

Perl Powershell主机文件编辑,perl,powershell,host,Perl,Powershell,Host,伙计们,我在将Perl脚本转换为powershell时遇到了一些问题,我需要一些帮助。在我们机器的主机文件中,我们阻止了测试环境的所有URL。在我的PERL脚本中,根据选择的环境,它将注释掉所选环境的行,以允许访问并阻止其他环境,这样测试人员就不会在错误的环境中错误地执行操作 我需要帮助转换到powershell 下面是我在PERL中的内容: sub editHosts { print "Editing hosts file...\n"; my $file = 'C:\\Windows\\Sys

伙计们,我在将Perl脚本转换为powershell时遇到了一些问题,我需要一些帮助。在我们机器的主机文件中,我们阻止了测试环境的所有URL。在我的PERL脚本中,根据选择的环境,它将注释掉所选环境的行,以允许访问并阻止其他环境,这样测试人员就不会在错误的环境中错误地执行操作

我需要帮助转换到powershell

下面是我在PERL中的内容:

sub editHosts {
print "Editing hosts file...\n";
my $file = 'C:\\Windows\\System32\\Drivers\\etc\\hosts';
my $data = readFile($file);
my @lines = split /\n/, $data;
my $row = '1';
open (FILE, ">$file") or die "Cannot open $file\n";
foreach my $line (@lines) {
    if ($line =~ m/$web/) { 
        print FILE '#'."$line\n"; }
    else {
        if ($row > '21') {
            $line =~ s/^\#*127\.0\.0\.1/127\.0\.0\.1/;
            $line =~ s/[#;].*$//s; }
        print FILE "$line\n"; }
    $row++;
}
close(FILE);
}
以下是我在Powershell中尝试的内容:

foreach ($line in get-content "C:\windows\system32\drivers\etc\hosts") {
if ($line -contains $web) {
$line + "#"
}
我尝试了一些变化,包括用宿主文件中的内容设置内容,等等

任何帮助都将不胜感激

谢谢,
Grant

-contains是一个“集合”运算符,而不是子字符串运算符。Try.Contains()或-like.

这将注释掉与变量
$word
匹配的行,同时从非匹配项(标题除外)中删除

用法:

Edit-Hosts -Web "PROD"

这是一个类似于弗罗德F.的答案,但我还不能评论添加我的2c值,所以必须提供一个替代答案

在本例中,从perl到PowerShell的一个陷阱似乎是,当我们使用
get content
获取文件内容时,它是一个“脱机”副本,即任何编辑都不会直接对文件本身进行。一种方法是将新内容编译成整个文件,然后将其写回磁盘

我假设
打印文件“some text\n”构造可能类似于PowerShell中的
“some text”| Out File$filename-Encoding ascii-Append
,尽管您可以使用后者(1)逐行写入新的/空文件,或者(2)接受您正在追加到现有内容

关于编辑主机文件,还有两件事:

  • 确保您的主机文件是ASCII编码的;在了解到以下情况时,我导致了一个关键企业应用程序(50k+用户)的严重中断
  • 您可能需要记住通过右键单击并选择以管理员身份运行来运行PowerShell/PowerShell ISE,否则您可能无法修改该文件
不管怎样,这里有一个使用
Out文件的上一个答案的版本:

$FileName = "C:\windows\system32\drivers\etc\hosts"
$web = "PROD"

# Get "offline" copy of file contents
$FileContent = Get-Content $FileName

# The following creates an empty file and returns a file
# object (type [System.IO.FileInfo])

$EmptyFile = New-Item -Path $FileName -ItemType File -Force

foreach($Line in $FileContent) {
  if($Line -match "$web") {
    "# $Line" | Out-File $EmptyFile -Append -Encoding ascii
  } else {
    "$Line" | Out-File $EmptyFile -Append -Encoding ascii
  }
}
编辑
  • ($Line-match“$web”)
    获取$web变量中的任何内容,并将其视为正则表达式。在我的示例中,我假设您只是想匹配一个简单的文本字符串,但您可能会尝试匹配一个IP地址,等等。您有两个选项:
    • 改用
      ($Line-like“*$web*”)
    • 将$web中的内容转换为转义正则表达式,即字面上匹配的正则表达式。使用
      ($Line-match[Regex]::Escape($web))
      执行此操作
  • 如果hosts文件第21行之后的任何一行与$web不匹配,您还希望删除该行中的注释。在perl中,您使用了s替换运算符;与PowerShell等效的是
    -更换
  • 所以。。。以下是该
    foreach
    循环的更新版本:

    $LineCount = 1
    
    foreach($Line in $FileContent) {
      if($Line -match [Regex]::Escape($web) {
        # ADD comment to any matched line
        $Line = "#" + $Line
      } elseif($LineCount -gt 21) {
        # Uncomment the other lines
        $Line = $Line -replace '^[# ]+',''
      }
    
      # Remove 'stacked up' comment characters, if any
      $Line = $Line -replace '[#]+','#'
    
      $Line | Out-File $EmptyFile -Append -Encoding ascii
    
      $LineCount++
    }
    
    更多信息

    如果您想验证其中的内容,然后添加条目,您可以使用以下设计为以交互方式运行并返回您在变量中指定的任何现有条目:

    注意:`t是'Tab'命令的powershell脚本方法

    $hostscontent
    
    # Script to Verify and Add Host File Entries
    
    $hostfile = gc 'C:\Windows\System32\drivers\etc\hosts'
    $hostscontent1 = $hostfile | select-string "autodiscover.XXX.co.uk"
    $hostscontent2 = $hostfile | select-string "webmail.XXX.co.uk"
    $1 = "XX.XX.XXX.XX`tautodiscover.XXX.co.uk"
    $2 = "webmail.XXX.co.uk"
    
    
    
    
    # Replace this machines path with a path to your list of machines e.g. $machines = gc \\machine\machines.txt
    $machines = gc 'c:\mytestmachine.txt'
    ForEach ($machine in $machines) {
    
                                    If ($hostscontent1 -ne $null) { 
                                    Start-Sleep -Seconds 1
                                    Write-Host "$machine Already has Entry $1" -ForegroundColor Green
    
    } Else { 
            Write-Host "Adding Entry $1 for $machine" -ForegroundColor Green
            Start-Sleep -Seconds 1
            Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "XX.XX.XXX.XX`tautodiscover.XXX.co.uk" -Force
    
    }
    
                                    If ($hostscontent2 -ne $null) {
                                    Start-Sleep -Seconds 1
                                    Write-Host "$machine Already has Entry $2" -ForegroundColor Green
    
    } Else {
            Write-Host "Adding Entry $2 for $machine" -ForegroundColor Green
            Start-Sleep -Seconds 1
            Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "XX.XX.XXX.XX`twebmail.XXX.co.uk" -Force
    
    }
        }
    

    我不懂Perl,所以我可能读错了。。。
    m/$web/
    =行不是以“web”开头吗?主机文件以“1.1.1.1 somedomain”开头,因此这永远不会起作用。请在所需更改之前和之后提供一个示例主机文件。好的:)else部分中的其余部分做什么?:)这正是一种愿望。。。但是,它不会删除旧行中的注释。。无论如何,也要做这一部分??见更新的答案。下次您应该包括一个示例(之前和之后),因为对于那些不懂perl的人来说,您想要什么还不清楚。但现在它不再工作了…别担心,你没有看到你把它包装在一个函数中!谢谢你的帮助!!很高兴我能帮忙。如果你认为这是正确答案,你应该用左边的复选标记作为答案。F工作得很好,我试着运行你的,但没有成功。它也没有出错。。。不知道为什么它不起作用,我可以再看一眼;我至少希望这是一个有用的答案今天我碰巧在工作中做了几乎完全相同的事情,所以我记忆犹新。如果它不起作用,最有可能的是
    -match
    部分不起作用。
    -match
    后面引号中的位被解释为正则表达式,因此如果$web包含特殊字符,则可能会出现问题。在我自己对上面代码的测试中,我设置了
    $web=“localhost”
    ,并使用默认的hosts文件,在这三行前面加了一个“#”。不过我会在答案中做一些修改。。。
    $hostscontent
    
    # Script to Verify and Add Host File Entries
    
    $hostfile = gc 'C:\Windows\System32\drivers\etc\hosts'
    $hostscontent1 = $hostfile | select-string "autodiscover.XXX.co.uk"
    $hostscontent2 = $hostfile | select-string "webmail.XXX.co.uk"
    $1 = "XX.XX.XXX.XX`tautodiscover.XXX.co.uk"
    $2 = "webmail.XXX.co.uk"
    
    
    
    
    # Replace this machines path with a path to your list of machines e.g. $machines = gc \\machine\machines.txt
    $machines = gc 'c:\mytestmachine.txt'
    ForEach ($machine in $machines) {
    
                                    If ($hostscontent1 -ne $null) { 
                                    Start-Sleep -Seconds 1
                                    Write-Host "$machine Already has Entry $1" -ForegroundColor Green
    
    } Else { 
            Write-Host "Adding Entry $1 for $machine" -ForegroundColor Green
            Start-Sleep -Seconds 1
            Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "XX.XX.XXX.XX`tautodiscover.XXX.co.uk" -Force
    
    }
    
                                    If ($hostscontent2 -ne $null) {
                                    Start-Sleep -Seconds 1
                                    Write-Host "$machine Already has Entry $2" -ForegroundColor Green
    
    } Else {
            Write-Host "Adding Entry $2 for $machine" -ForegroundColor Green
            Start-Sleep -Seconds 1
            Add-Content -Path C:\Windows\System32\drivers\etc\hosts -Value "XX.XX.XXX.XX`twebmail.XXX.co.uk" -Force
    
    }
        }