【问题标题】:Paragraph conditional nested regular expression (recursion)段落条件嵌套正则表达式(递归)
【发布时间】:2017-07-01 06:40:16
【问题描述】:

我需要一个与段落匹配的正则表达式:'&Start a'(示例文本中的第一个)直到 '&end a'(示例文本的最后一个结尾)。问题是有时'&end a' 没有明确指定,有时写成'&end'。当您有 '&Start b' 和 '&end b' (有时也是 '&end' 时,问题会更大,因此会造成混乱)。

此正则表达式的目标示例块是(抱歉将其作为代码块):

junk text

&Start a <

fulfilling text

fulfilling text

&Start b

&Start c

&end c

fulfilling text

&end

&end <

junk text

所以正则表达式应该匹配所有以包含

这不是一个简单的实现。我正在使用的表达式如下:

&start a([^&]*)(&end a|&end) 

这可以很好地隔离 '&start a' '&end' 段落,但是当其他 '&start Y' 行介于两者之间时,脚本会变得混乱。 我可能会使用一些跳过不需要的块的 If 语句......这是一个更复杂的案例方法:

junk text

&Start a <

fulfilling text

fulfilling text

&Start b

&Start c

&end

fulfilling text

&end

&end <

junk text

没有指定任何'&end'。 注意1:'&start X' 总是被定义,但'&end X' 也可以是'&end',但总是对应于最接近的预先开始。 注意2:由于堆栈溢出错误,我无法对正则表达式的结构进行太多更改,而是将其调整为适应这种特定情况。

对不起,奇怪的解释,但我希望有人能找到任何可行的建议。

谢谢

编辑:

#@ -split "`n" | ForEach-Object { $_.trim() } |

$files = Get-ChildItem "$PSScriptRoot" # root path

for($i=0; $i -lt $files.Count; $i++){

    #iterate through files from the current folder.
    $data = Get-Content -Path $files[$i].FullName

    # parse DisabledFeatures.txt file as array of strings (1 string per line of the file)
    $feature = Get-Content DisabledFeatures.txt

    #iterate for each string entry in $feature array (read from txt file)
    for($counter=0; counter -lt $feature.Count; counter++){

        #retrieve array value to use it in the main algorythm
        $groupID = "$feature"

        $data | ForEach-Object -Begin { $ignore = $false; $levels = 0 } -Process {
            #Start ignoring text after we've found the trigger
            if($_ -match "^`#ifdef $groupID") { $ignore = $true }   
            #Track nested groups
            elseif($ignore) {
                if ($_ -match '^`#ifdef') { $levels++ }
                elseif ($_ -match '`#endif') {
                    if($levels -ge 1) { $levels-- }
                    #If no nesting, we've hit the end of our targeted group. Stop ignoring
                    else { $ignore = $false }
                }
            }
            #Write line
            else { $_ }
        }  
    }
}

【问题讨论】:

  • 您不能为此使用正则表达式,您需要一个解析器。 Obligatory link
  • 不太清楚,见regex101.com/r/GJ7dG6/1 - 你需要这样的东西吗?它是用 Java 还是 Powershell 编写的?
  • java.不抱歉,'
  • 您希望它在匹配的$end“标签”处结束,因为两者之间可以有多个开始/结束标签。就像我说的那样,正则表达式是不可能的 (并保持理智)
  • @WiktorStribiżew - 这适用于&amp;Start a,但不适用于$Start b

标签: java regex powershell if-statement paragraph


【解决方案1】:

纯正则表达式解决方案可能不是解决此问题的最佳解决方案。它可能可以完成,但它可能非常复杂且难以阅读。我会为此使用一个简单的解析器。示例:

function Remove-TextGroup {
    param(
        [Parameter(Mandatory=$true)]
        [string[]]$Data,
        [Parameter(Mandatory=$true)]
        [string]$GroupID
    )

    $Data | ForEach-Object -Begin { $ignore = $false; $levels = 0 } -Process {
        #Start ignoring text after we've found the trigger
        if($_ -match "^&start $GroupID") { $ignore = $true }   
        #Track nested groups
        elseif($ignore) {
            if ($_ -match '^&start') { $levels++ }
            elseif ($_ -match '^&end') {
                if($levels -ge 1) { $levels-- }
                #If no nesting, we've hit the end of our targeted group. Stop ignoring
                else { $ignore = $false }
            }
        }
        #Write line
        else { $_ }

    }
}

用法:

$data = @"
junk text

&Start a <

fulfilling text

fulfilling text

&Start b

&Start c

&end

fulfilling text

&end

&end <

junk text
"@ -split "`n" | ForEach-Object { $_.trim() } |
#Remove empty lines
Where-Object { $_ }

Remove-TextGroup -Data $data -GroupID a    

#Or to read from file.. 
#$data = Get-Content -Path Myfile.txt
Remove-TextGroup -Data $data -GroupID a    

输出:

junk text
junk text

如果文件很大,我会优化上面的示例以使用streamreader 来读取文件。

【讨论】:

  • a 中的测试也应该被删除。我将尝试实施您的解决方案。有什么方法可以创建可以从批处理文件运行的 powershell 脚本?
  • 为什么?只在a组内。你不是说要跳过b组和c组吗?如果我们忽略“test inside a”,那么我们也可以在开始 b 时停止。
  • 必须删除 'end a' 之前的所有内容。即使它在a块中。对不起我的解释..
  • 我以为你想保留 a 组。您是否要删除组 a 的内容(不是开始和结束)并保留文档的其余部分?如果是这样,应该在问题中更好地指定它。所需的输出样本也会有所帮助。
  • 我想完全删除组a,包括开始a及其对应的结束。我稍后会更新问题。再次抱歉。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 1970-01-01
  • 2012-01-16
  • 2010-09-12
  • 2018-10-13
  • 2011-04-06
  • 1970-01-01
相关资源
最近更新 更多