【问题标题】:Get-Content & combine "continued lines"获取内容并结合“续行”
【发布时间】:2015-12-16 18:25:53
【问题描述】:

我使用 Get-Content 将一个 txt 文件拉入一个数组,该数组使用 _ 作为行继续标记,并且连续行的数量可以是从一到多的任何值。所以文本可能看起来像这样......

Jrn.Directive "DocSymbol"  _
, "[Commercial-Default.rte]"
Jrn.Directive "GlobalToProj"  _
, "[Commercial-Default.rte]", "Floor Plan: Level 1" _
, 0.01041666666667 _
, 1.00000000000000, 0.00000000000000, 0.00000000000000 _
, 0.00000000000000, 1.00000000000000, 0.00000000000000 _
, 0.00000000000000, 0.00000000000000, 1.00000000000000 _
, 0.00000000000000, 0.00000000000000, 0.00000000000000

我想在不换行的情况下重新格式化,我想知道是否有一些我没有看到的超级优雅的方法?因为我认为前进的方向是 $array 中的 foreach $line,如果行 EndsWith("") 为行索引设置了起始索引,则向前搜索直到一行没有 EndsWith(" ") 并设置结束索引,组合位并写入临时数组,然后在主循环继续读取行时跳过两个索引之间的差异。如果没有更详细的伪代码就有意义。 无论如何,看起来笨拙不雅,不知道有没有更好的方法?

我最初的想法是 Get-Content 可能内置了一些东西,但看起来您可以定义的唯一分隔符是行尾(默认为 \n)。

因此,根据 Anthony 的意见,并意识到我需要先合并行,然后删除不相关的行(开始时可能是多行),我现在有了这个。

$target = 'Z:\Support\Px 3.0\RFO Benchmark\Journal Cleanup\journal.0010.txt'
$cleanFile = 'Z:\Support\Px 3.0\RFO Benchmark\Journal Cleanup\journal.0010.CLEAN.txt'

$sourceFile = Get-Content $target

$cleanData = @()


function Relavant {
    [CmdletBinding()]
    param (
        [string]$line
    )

    $irrelevant = @('Jrn.Directive “Username"', 'Jrn.Directive "IdleTimeTaskSymbol"', 'Jrn.Directive "WindowSize"', 'Jrn.Size')

    foreach ($item in $irrelevant) {
        if ($line.StartsWith($item)) {
            $relevant = $false
        } else {
            $relevant = $true
        }
    }

$relevant    
}

$string = ''
$continue = $false
$tempData = $(foreach ($line in $tempData) {
    if ($line -match '^[^,]') {
        $string = ''
        $continue = $true
    }
    if ($continue) {
        $string += $line
    }
    if ($line.EndsWith('_')) {
        $continue = $true
    } else {
        $continue = $false
        $string -replace '\s?_'
    }
})

# Remove comments & irrelevant lines and do basic formatting
foreach ($line in $tempData) {
    $line = $line.Trim()
    if (-not ($line.StartsWith("'"))) {
        if (Relavant $line) {
            $line = $line -replace " ,", ","
            $line = $line -replace '\s+', ' '
            $cleanData += $line
        }
    }
}

Add-Content $cleanFile "' Cleaned by PxJournalCleaner`n"
foreach ($line in $cleanData) {
    Add-Content $cleanFile $line
}

它运作良好,但我怀疑如果没有别的原因,我会用另一种方法再次实施它,只是为了教育因素。我也不确定我是否完全理解安东尼的方法发生了什么,所以我显然还有一些事情要做。谢谢大家!

【问题讨论】:

  • 您能否展示一下您描述得如此雄辩的代码? :)
  • 好吧,代码还不存在,雄辩与否。我正试图弄清楚如何去做,这真是一团糟,这让我觉得我错过了更好的方法。也就是说,无论如何,如果没有其他原因,当一个人已经以错误的方式做某事时,我会更好地欣赏做某事的正确方法。 ;)
  • 您是否至少有 PowerShell 3.0?这些文件通常有多大?

标签: powershell


【解决方案1】:

您可能应该使正则表达式匹配更精确一点,但它对我有用

$file = gc 'C:\temp\new 1.txt'

$string = ''
$cont = $false
$result = $(foreach ($line in $file) {
    if ($line -match '^[^,]') {
        $string = ''
        $cont = $true
    }
    if ($cont) {
        $string += $line
    }
    if ($line.EndsWith('_')) {
        $cont = $true
    } else {
        $cont = $false
        $string -replace '\s?_'
    }
})

$result

【讨论】:

  • 嗯,现在差不多已经确定了,不是吗。谢谢安东尼!
【解决方案2】:

你的方法似乎很好,虽然我可能一次只做一行。

你可以这样做:

# read the wrapped lines from file
$lines = Get-Content C:\yourfile.txt
# initialize an array with a single empty string + a cursor that we'll use to keep track of the last index
$unwrappedLines = ,""
$cursor = 0
# iterate over the input strings
foreach($line in $lines){
    if($line.EndsWith(" _")){
        # Line is to be continued, remove line continuation character and add the rest of the string to the current index in our new array
        $unwrappedLines[$cursor] += $line.Substring(0,$line.Length - 2)
    }
    else
    {
        # Line is not to be continued, add value as-is to current index
        $unwrappedLines[$cursor] += $line
        # Then increment our index cursor and initalize the next string in the array
        $unwrappedLines[++$cursor] = ""
    }
}

【讨论】:

  • 这太棒了,谢谢分享! $unrappedLines = ,"" OR $unrappedLines = @() 之间是否存在差异(性能或其他方面)
  • 不,但有一个 功能 区别 - @() 初始化一个 empty 数组(所以我们无法做到 @()[0] ,因为在索引 0 处不存在任何内容),而 ,"" 为我们提供了一个长度为 1 的数组,其第一个值是空字符串。 @AnthonyStringer 的解决方案更像是 powershell-esque,我想说
  • 我认为你解释得很好,但我做不到 $a = ,''; $a[0] = 1; $a[1] = 2。另外,不知道如何在 cmets 部分指定代码。
  • 查看 else 块中的最后一条语句 :-)
  • 是的,仍然不适合我:( $num=0; $a=,""; $a[$num]=1; $a[++$num]="".我可以让它工作的唯一方法是这样的: $a=@(); $a+=1;$a+=2
【解决方案3】:

如果文件足够小,只需将其作为一个字符串读入,然后将所有 _newlines 替换为空。

(Get-Content -Raw "c:\temp\test.txt") -replace "_`r`n"

-Raw 在 3.0 中工作。如果你没有,那么Out-String 来救援。

(Get-Content "c:\temp\test.txt" | Out-String) -replace "_`r`n"

只需要找到后跟新行的任何下划线并将其删除即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2016-10-30
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多