【问题标题】:Powershell - Cut, combine and simplify lines in a filePowershell - 剪切、合并和简化文件中的行
【发布时间】:2019-11-04 21:44:24
【问题描述】:

我有一个包含以下几行的 file.txt:

Other lines...
...
Microsoft .NET Core SDK 2.1.801 (x64)
Microsoft .NET CoreRuntime For CoreCon
Microsoft .NET CoreRuntime SDK
Microsoft .NET Framework 3.5 Targeting Pack (enu)
Microsoft .NET Framework 4 Multi-Targeting Pack
Microsoft .NET Framework 4.5 Multi-Targeting Pack
Microsoft .NET Framework 4.5.1 Multi-Targeting Pack
Microsoft .NET Framework 4.5.1 Multi-Targeting Pack (ENU)
Microsoft .NET Framework 4.5.1 SDK
Microsoft .NET Framework 4.5.2 Multi-Targeting Pack
Microsoft .NET Framework 4.5.2 Multi-Targeting Pack (ENU)
Microsoft .NET Framework 4.6 Targeting Pack
Microsoft .NET Framework 4.6.1 Targeting Pack
Microsoft .NET Framework 4.7.1 Doc Redirected Targeting Pack (ENU)
Microsoft .NET Framework 4.7.1 Targeting Pack
Microsoft .NET Framework 4.7.2 SDK
Microsoft .NET Framework 4.7.2 Targeting Pack
Microsoft .NET Framework 4.7.2 Targeting Pack (ENU)
Microsoft .NET Framework Cumulative Intellisense Pack for Visual Studio (ENU)
Microsoft .NET Native SDK
Windows Desktop SDK
...
Etc

如何将多条 .NET 行变成一行:

Microsoft .NET Framework [3.5] [4] [4.5] [4.5.1] [4.5.2] [4.6] [4.6.1] [4.7.1] [4.7.2]

并删除此块中所有其他与 .NET 相关的行?

(使用 powershell。)

【问题讨论】:

标签: .net powershell shell command-line


【解决方案1】:

另一种选择,不使用 ArrayList:

# read the file as string array
$lines = Get-Content -Path 'file.txt'
# create a regex string to capture the prefix and version
$regex    = '^(?<prefix>Microsoft \.NET Framework\s*)(?<version>[\d\.]+)'
$versions = @()
$count    = 0
$index    = -1

$result = $lines | ForEach-Object {
    if ($_ -match $regex) {
        if ($index -lt 0) {
            # remember the index of this line
            $index = $count
            # output just the prefix for now, we will add the versions to it later
            $matches['prefix']
            $count++
        }
        # store the version in an array
        $versions += $matches['version']
    }
    else { $_ ; $count++}  # no match, simply output the line and increase $count

}

$result[$index] += ($versions | Sort-Object -Unique | ForEach-Object { '[{0}]' -f $_ }) -join ' '

输出:

Other lines...
...
Microsoft .NET Core SDK 2.1.801 (x64)
Microsoft .NET CoreRuntime For CoreCon
Microsoft .NET CoreRuntime SDK
Microsoft .NET Framework [3.5] [4] [4.5] [4.5.1] [4.5.2] [4.6] [4.6.1] [4.7.1] [4.7.2]
Microsoft .NET Framework Cumulative Intellisense Pack for Visual Studio (ENU)
Microsoft .NET Native SDK
Windows Desktop SDK
...
Etc


编辑

如果要删除所有其他以Microsoft .NET 开头的行,请将上面的代码更改为:

# read the file as string array
$lines = Get-Content -Path 'file.txt'
# create a regex string to capture the prefix and version
$regex    = '^(?<prefix>Microsoft \.NET Framework\s*)(?<version>[\d\.]+)'
$versions = @()
$count    = 0
$index    = -1

$result = $lines | ForEach-Object {
    if ($_ -match $regex) {
        if ($index -lt 0) {
            # remember the index of this line
            $index = $count
            # output just the prefix for now, we will add the versions to it later
            $matches['prefix']
            $count++
        }
        # store the version in an array
        $versions += $matches['version']
    }
    elseif ($_ -notlike 'Microsoft .NET*') { 
        # no match, output the line and increase $count if it does not start with "Microsoft .NET"
        $_
        $count++ 
    }   
}

$result[$index] += ($versions | Sort-Object -Unique | ForEach-Object { '[{0}]' -f $_ }) -join ' '

# output on screen
$result
Other lines...
...
Microsoft .NET Framework [3.5] [4] [4.5] [4.5.1] [4.5.2] [4.6] [4.6.1] [4.7.1] [4.7.2]
Windows Desktop SDK
...
Etc

【讨论】:

    【解决方案2】:

    如果您想在文件中的哪个位置插入自定义字符串并不重要,您可以执行以下操作:

    $hash = [collections.arraylist]@()
    [collections.arraylist]$out = switch -regex -file file.txt {
        'Microsoft .NET Framework (\d[\d\.]*)' {
            if ($hash -notcontains "[$($Matches[1])]") {
                [void]$hash.Add(("[{0}]" -f $Matches[1])) }
        }
        default { $_ }
    }
    $out,("Microsoft .NET Framework {0}" -f "$hash")
    

    如果字符串的插入点很重要,您将需要一些方法来确定该行号。有很多方法可以做到这一点。下面读取文件一次,循环遍历文件的每一行,并跟踪包含第一个字符串匹配的行号。

    $hash = [collections.arraylist]@()
    $firstIndex = 0
    $data = Get-Content file.txt
    [collections.arraylist]$out = for ($i = 0; $i -lt $data.count; $i++) {
        if ($data[$i] -match 'Microsoft .NET Framework (\d[\d\.]*)') {
            if (!$firstIndex) {
                $firstIndex = $i
            }
            if ($hash -notcontains "[$($Matches[1])]") {
                [void]$hash.Add(("[{0}]" -f $Matches[1]))
            }
        }
        else {
            $data[$i]
        }
    }
    
    $out.Insert($firstIndex,("Microsoft .NET Framework {0}" -f "$hash"))    
    $out
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-29
      • 1970-01-01
      • 1970-01-01
      • 2021-02-25
      • 2019-11-14
      相关资源
      最近更新 更多