【问题标题】:Powershell capture a text pattern in files and replace characters in the patternPowershell 捕获文件中的文本模式并替换模式中的字符
【发布时间】:2021-05-13 15:41:36
【问题描述】:

我拥有的是:

我做了一个简单的Powershell脚本来替换文本文件的内容并重写文件(UTF8编码很重要):

((Get-Content -path *.adoc -Raw -Encoding utf8) -replace '\[.dfn .term]#.*#','[.dfn .term]_.*_') | Set-Content -Path *.adoc -Encoding utf8

当我尝试像这样运行脚本时,我发现我正在用纯文本字符串替换正则表达式字符串。

我想要实现的是:

找到以[.dfn .term] 开头、在## 之间有任意数量的字符的行,并将# 替换为_。保持[.dfn .term]# everything between # 不变。

我无法将所有# 替换为_,因为也可能存在[.keyword]#something# 之类的文本,并且需要将# 替换为*。此外,something 可以是任何东西——一个词或一个短语。

处理模式和 RegEx 组超出了我的知识范围。我将不胜感激。

示例:

我有: 一个句子是[.dfn .term]#Words# 的字符串,它有一个完成的[.keyword]#Thought#。句子形式为[.dfn .term]#Paragraphs#[.dfn .term]#Paragraphs# 表单文本。文字很酷。

我想拥有: 一个句子是[.dfn .term]_Words_ 的字符串,它有一个完成的[.keyword]*Thought*。句子形式为[.dfn .term]_Paragraphs_[.dfn .term]_Paragraphs_ 表单文本。文字很酷。

【问题讨论】:

  • 能否贴出一些你可以拥有的值和替换后的期望值的例子,我想会更容易理解和帮助你。
  • @SantiagoSquarzon 我添加了一个示例。

标签: regex powershell


【解决方案1】:

将这些正则表达式与组一起使用可以帮助您:

$lines = Get-Content -Path C:\file.txt -Encoding UTF8 -Raw
$option = [System.Text.RegularExpressions.RegexOptions]::Singleline 

$pattern1 = [regex]::new("(\[\.dfn \.term])#(.*?)#", $option)
#be careful simple quote is important here
$lines = $pattern1.Replace($lines, '$1_$2_')

$pattern2 = [regex]::new("(\[what you want])#(.*?)#", $option)
$lines = $pattern2.Replace($lines, '$1*$2*')

$lines | Set-Content -Path C:\result.txt -Encoding UTF8 

测试文件:

[.dfn .term]#azaeaeae#

[.dfn .term]#errrr# sqsqsqs


[.dfn .term]#errrr# sqsqsqs
eaeaeaeae
aeaeae
[.dfn .term]#errrr# [.keyword]#something# #errrr#

结果:(使用第二个模式 .keyword)

[.dfn .term]_azaeaeae_


[.dfn .term]_errrr_ sqsqsqs


[.dfn .term]_errrr_ sqsqsqs
eaeaeaeae
aeaeae
[.dfn .term]_errrr_ [.keyword]*something* #errrr#

你也可以写:

$lines = (Get-Content -path C:\yourfile.txt -Raw -Encoding utf8) `
                -replace '(\[\.dfn \.term])#(.*?)#', '$1_$2_' `
                -replace '(\[\.keyword])#(.*?)#', '$1*$2*'

如果需要,您可以使用命名组:

$pattern1 = [regex]::new("(?<begin>\[\.dfn \.term])#(?<text>.*?)#", $option)
#be careful simple quote is important here
$lines = $pattern1.Replace($lines, '${begin}_${text}_')

如果你有很多不同的模式,你可以把它们放在一个对象中:

$patterns = @{
 '(\[\.dfn \.term])#(.*?)#' = '$1_$2_' ;
 '(\[\.keyword])#(.*?)#' = '$1*$2*'
}
$option = [System.Text.RegularExpressions.RegexOptions]::Singleline 

foreach($k in $patterns.Keys){
  $pat = [regex]::new($k, $option)
  $lines = $pat.Replace($lines, $patterns.$k)
}

【讨论】:

  • 脚本由于某种原因没有被替换。它运行时不会返回任何错误,但不会对文件进行任何更改。
  • 所以你有一个问题模式/你的文件中有什么..你确定空间不是标签..或其他问题..我对测试文件没有问题..你能发布您的测试文件的一部分?
  • 不要忘记转义一些特殊字符,例如([.
  • 不知道我做错了什么。我完全复制了脚本来测试它。我将一个新文件放到磁盘的根目录。该文件包含 5 行 - 3 行有 [.dfn .term]#Word# 加上 2 个空行。我在脚本中唯一更改的是从 C: 到 D: 的文件路径。需要Set-Content来写文件吗?
  • 我用 Set-content 保存文件,但结果已经在变量中了..
【解决方案2】:

您想创建一个正则表达式,仅匹配 [.dfn .term] 之后和行尾的 # 符号。

这是一个例子:

"[.dfn .term]# everything between #" -replace "(?<=\[\.dfn \.term\])#|#$", "_"

...导致:[.dfn .term]_ _ 之间的所有内容

下面是它的分解方式:

(?

# - 匹配井号

| - 或者

#$ - 匹配行尾的井号

【讨论】:

  • 你说#$ - matches the pound sign at the end of the line。如果我搜索的内容不是在的末尾,而是在一个段落或其他任何地方怎么办? UTF8 编码会被保留吗?
  • 另外,我是否可以用正则表达式替换everything between,因为它可能因一个实例与另一个实例不同而异?
  • 鉴于您的新示例,您可以使用: (?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
  • 2021-12-12
  • 1970-01-01
  • 2013-06-26
  • 1970-01-01
相关资源
最近更新 更多