批处理之家's Archiver

5i365 发表于 2022-3-31 17:35

PowerShell把hash表定义还原回字面字符串

此贴由 另一贴引出 [url=http://www.bathome.net/thread-62168-1-1.html]http://www.bathome.net/thread-62168-1-1.html[/url]

下面的代码, 输出的结果是: hash表对象的属性,即[color=#0000ff]蓝色字[/color], 我想输出hash对象的定义的字符串,即[color=#ff0000]红色字,[/color][color=#000000]
[/color]
我找到了【hash表对象定义还原回字符串】的下面关键代码, 有两种,效果相同, 但是还差首和尾的定义, 怎么接上? 【三行代码的结果也有瑕疵,值没有被双引号引起来】
[size=12px]$hash.GetEnumerator() | %{[/size]
[size=12px] $_.key + "=" + $_.Value[/size]
[size=12px]}[/size][size=12px]
[/size]
[size=12px]----------------------------------上面是用枚举器的方法,下面是用遍历键值的方法[/size]
[size=12px]foreach ($key in $hash.keys) {[/size][size=12px]
$key + "=" + $hash[$key][/size]
[size=12px]}[/size]

[size=12px]感觉从正则匹配的地方生成可能更简单,
[/size]或可能还有更好的思路和方法, 请求路过高手支招, 提前感谢!

[color=#000000]-----------------------------------------------------------------------------------------------------------------------------

[/color][color=#0000ff]Name                           Value[/color]
[color=#0000ff]----                           -----[/color]
[color=#0000ff]日本                             "在东京"[/color]
[color=#0000ff]美国                             "在纽约"[/color]
[color=#0000ff]南非                             "在刚果"[/color]

------------------------------------------------------------------
[color=#ff0000]$hash = [ordered]@{[/color]
[color=#ff0000]
日本 = "在东京"[/color]
[color=#ff0000]
美国 = "在纽约"[/color]
[color=#ff0000]
南非 = "在刚果"[/color]
[color=#ff0000]}[/color][code]$s = @"
岁月难得沉默
秋风厌倦漂泊
夕阳赖着不走
挂在墙头舍不得我
昔日伊人耳边话
已和潮声向东流
再回首
#开始
      黄种人"在东京", //日本
             白人"在纽约", //美国

"在刚果",//南非
        黑人//印度

#结束
往事也随枫叶一片片落
爱已走到尽头
恨也放弃承诺
命运自认幽默
想法太多由不得我
壮志凌云几分酬
知己难逢几人留
"@

$txt = $s -split '\n' -join "|"

$pattern1 = "#开始(.*)#结束"
$pattern2 = '("\w+"),\s?//(\w+)'
$hash = [ordered]@{ }

if ($txt -match $pattern1)
{
        $target = $matches[1].split('|')
}

foreach ($line in $target)
{
        if ($line -match $pattern2)
        {
                $hash[$matches[2]] = $matches[1]
        }
}
$hash[/code]

went 发表于 2022-3-31 20:12

用-f格式化就很好操作[code]$s = @'
岁月难得沉默
秋风厌倦漂泊
夕阳赖着不走
挂在墙头舍不得我
昔日伊人耳边话
已和潮声向东流
再回首
#开始
      黄种人"在东京", //日本
             白人"在纽约", //美国

"在刚果",//南非
        黑人//印度

#结束
往事也随枫叶一片片落
爱已走到尽头
"在刚f果",//南非
恨也放弃承诺
命运自认幽默
想法太多由不得我
壮志凌云几分酬
知己难逢几人留
'@

$hash = [ordered]@{}
if($s -match '(?s)#开始(.*?)#结束'){
    [regex]::Matches($Matches[1],'(?m)"(.+?)",\s*//(.+?)$') | foreach { $hash.($_.Groups[2].Value) = $_.Groups[1].Value }
}

$hash.Keys | foreach { '{0} = "{1}"' -f $_,$hash[$_] }[/code]

5i365 发表于 2022-3-31 21:23

[i=s] 本帖最后由 5i365 于 2022-3-31 21:24 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=253609&ptid=62187]2#[/url] [i]went[/i] [/b]


  大侠牛X, 确实好理解多了, 怎样生成下面格式的字面值?  我是想生成下面的字面值, 然后存到变量$h中, 后面想显示的时候, 直接放出$h变量
[color=#ff0000]$hash = [ordered]@{[/color][color=#ff0000]
    日本 = "在东京"[/color][color=#ff0000]
    美国 = "在纽约"[/color][color=#ff0000]
    南非 = "在刚果"[/color]
[color=#ff0000]}[/color]

5i365 发表于 2022-3-31 21:36

[i=s] 本帖最后由 5i365 于 2022-3-31 21:53 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=253609&ptid=62187]2#[/url] [i]went[/i] [/b]


   我自己改成下面这样, 会多一个空行, 另外感觉太绕
[code]$hash.Keys | foreach { '{0} = "{1}"' -f $_, $hash[$_] } | Out-String | tee -var mid | Out-Null
$start = '$hash = [ordered]@{'
$end = '}'

$h = @"
$start
$mid
$end
"@

$h[/code]

went 发表于 2022-3-31 21:54

&{
    代码块
}
可以把整个代码块的输出转换为一个字符串[code]$hash = [ordered]@{}
if($s -match '(?s)#开始(.*?)#结束'){
    [regex]::Matches($Matches[1],'(?m)"(.+?)",\s*//(.+?)$') | foreach { $hash.($_.Groups[2].Value) = $_.Groups[1].Value }
}

$h =
&{
    '$hash = [ordered]@{'
    $hash.Keys | foreach { '{0}{1} = "{2}"' -f "`t",$_,$hash[$_] }
    '}'
}

$h[/code]

5i365 发表于 2022-3-31 21:57

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=253630&ptid=62187]5#[/url] [i]went[/i] [/b]


大侠实在太牛X了, [url=http://www.baidu.com/link?url=8PvM-IFbzjCONCYhfIbugbb4UAgE7ZYN0C0J0wu0PEmAA2co817ixuN0QeB4u1berimAoyds3krIY8ZZ_0FYkMnKk1Q4HfxT59tlDW7AqEJhtDcWabcagaJnXrC-eZdDpAKGb18qriASmab5LcjwZ9fQgUJCrvzYXi_9diumNdOJMPhlp7WfX8HaJzQPSquS][color=#0000ff]精干高效,炉[/color][/url][color=#0000ff]火纯青[/color]!!

went 发表于 2022-3-31 22:01

[i=s] 本帖最后由 went 于 2022-3-31 22:05 编辑 [/i]

纠正一下
&{
    代码块
} 转换为Object数组

&{
    代码块
} | Out-String 转换为字符串

5i365 发表于 2022-4-1 07:21

[i=s] 本帖最后由 5i365 于 2022-4-1 07:24 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=253632&ptid=62187]7#[/url] [i]went[/i] [/b]


   感谢大侠提醒, gettype看了一下, 确实如此, 另外大侠能解惑一下您正则中的符号的含义吗?
for_flr 大侠写的正则如下, [size=12px]我能理解, [/size]
$pattern1 = "#开始(.*)#结束"
$pattern2 = '("\w+"),\s?//(\w+)'

--------------------------------------------------
您写的正则如下
'(?s)#开始(.*?)#结束'
'(?m)"(.+?)",\s*//(.+?)$'

--------------------------------------------------
量词+或*后加了? 应该是匹配尽可能的少
但是正则前都多了括号[size=12px](?s)和[/size][size=12px](?m)[/size]
(?m)我好像在哪里看到过, 说的是匹配多行, 但是[size=12px](?s)这个参数没找到相关资料, ps官方的MSDN也没找到,  [/size]
[size=12px]大侠能解释一下它的含义吗? 能引用一个资料出处就好了, 再次感谢.[/size]
[size=12px]放上官方PS的正则链接供大家参考[/size]
[size=12px]https://docs.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/about/about_regular_expressions?view=powershell-7.2[/size]

went 发表于 2022-4-1 11:32

这里面有关于单行和多行匹配的详细介绍
[url]https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/regular-expression-options[/url]

5i365 发表于 2022-4-1 16:38

[i=s] 本帖最后由 5i365 于 2022-4-1 19:21 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=253649&ptid=62187]9#[/url] [i]went[/i] [/b]

非常感谢大侠的指引!!!原来是单行模式, 这样就不用 像 for_flr 大侠代码那样, 先用 | 拼接了, 方便了很多

刚又入了一个坑, 我把要处理的文本外置存为了s.txt, 再次执行后, =号后面换行了, 结果如下!

$hash = [ordered]@{

日本
= "在东京"

美国
= "在纽约"

南非
= "在刚果"
}



[code]$s = gc s.txt -enc UTF8 -raw

$hash = [ordered]@{ }
if ($s -match '(?s)#开始(.*?)#结束')
{
        [regex]::Matches($Matches[1], '(?m)"(.+?)",\s*//(.+?)$') |
        foreach { $hash.($_.Groups[2].Value) = $_.Groups[1].Value }
}


$h = &{
        '$hash = [ordered]@{'
        $hash.Keys | foreach { '{0}{1} = "{2}"' -f "`t", $_, $hash[$_] }
        '}'
}

$h[/code]

went 发表于 2022-4-1 19:32

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=253663&ptid=62187]10#[/url] [i]5i365[/i] [/b]


    我运行没问题

5i365 发表于 2022-4-1 20:49

[i=s] 本帖最后由 5i365 于 2022-4-1 20:51 编辑 [/i]

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=253671&ptid=62187]11#[/url] [i]went[/i] [/b]


我在powershell studio 里, 显示换行了, 但是我在powershell ISE里, 显示是好的, 但是定向后, 也换行了,
$h > "C:\Users\Administrator\Desktop\aaa.txt"
s.txt 下载 [url=https://send.cm/d/9oH1]https://send.cm/d/9oH1[/url]
[code]$s = gc "C:\Users\Administrator\Desktop\s.txt" -enc UTF8 -raw
$s -match '(?s)#开始(.*?)#结束'
$matches[0]

$hash = [ordered]@{ }
if ($s -match '(?s)#开始(.*?)#结束')
{
        [regex]::Matches($Matches[1], '(?m)"(.+?)",\s*//(.+?)$') |
        foreach { $hash.($_.Groups[2].Value) = $_.Groups[1].Value }
}


$h = &{
        '$hash = [ordered]@{'
        $hash.Keys | foreach { '{0}{1} = "{2}"' -f "`t", $_, $hash[$_] }
        '}'
}

$h>"C:\Users\Administrator\Desktop\aaa.txt"[/code]

went 发表于 2022-4-1 21:14

[i=s] 本帖最后由 went 于 2022-4-1 21:16 编辑 [/i]

正则改一下,把末尾的换行符去掉[code]'(?m)"(.+?)",\s*//(\S+?)\s$'[/code][code]'(?m)"(.+?)",\s*//\s*(.+?)\s*$'[/code]

5i365 发表于 2022-4-1 21:20

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=253684&ptid=62187]13#[/url] [i]went[/i] [/b]


   大侠牛X,  显示和输出都没换行了.
正则真是字符串处理的万金油啊,!!!

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.