Get-Content&结合"续行"

时间:2015-12-16 18:25:53

标签: powershell

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

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 $行,如果行EndsWith(" ")设置行索引的起始索引,则向前搜索直到一行没有EndsWith(" ")并设置一个结束索引,将这些位组合并写入临时数组,然后在主循环继续时跳过两个索引之间的差异读行。如果没有更详细的伪代码,这是有道理的。 在任何情况下,它看起来都很笨拙和不优雅,我想知道是否有更好的方法?

我最初的想法是Get-Content可能内置了一些内容,但看起来你可以定义的唯一分隔符是End of Line(默认为\ n)。

所以,基于安东尼的输入,并意识到我需要首先组合线,然后删除不相关的线(这可能是多行开头)我现在有了这个。

$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
}

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

3 个答案:

答案 0 :(得分:2)

你应该让正则表达式匹配更精确,但它对我有用

$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

答案 1 :(得分:1)

你的方法似乎完全没问题,虽然我可能一次只做一行。

您可以执行以下操作:

# 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] = ""
    }
}

答案 2 :(得分:0)

如果文件足够小,只需将其作为一个字符串读取,并将所有_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"

只需要找到一个后跟新行的下划线并删除它。