我正在尝试创建一个文件解析器,它将获取一个原始输入文件,然后创建一个新文件,其中包含正确顺序的所有元素,并使用适当的新行,以便另一个解析器可以读取它。
所以我的文件是PGN(Portable Games Notation)。这些文件用于国际象棋以记录人们在计算机上玩的游戏。
他们看起来像:
--------------------------------------
[Event "Computer chess game"]
[Date "2015.10.28"]
[Round "?"]
[White "White Player"]
[Black "Black Player"]
[Result "1-0"]
[BlackElo "2400"]
[ECO "A25"]
[Opening "English"]
[Time "10:39:20"]
[Variation "Closed"]
[WhiteElo "2400"]
[Termination "normal"]
[PlyCount "63"]
[WhiteType "human"]
[BlackType "human"]
1. f3 e6 2. g4 Qh4# 1-0
-------------------------------
在Reddit的/ r /象棋上,他们可以使用[pgn][/pgn]
将游戏包围起来,然后它会创建一个可玩的棋盘,让您或其他人可以逐步完成您的游戏并为您提供建议等。
问题是我玩的网站,PGN如上所述。 / r / chess解析器不喜欢它。
它更倾向于将每一个动作分开:
1. f3 e6
2. g4 Qh4# 1-0
由于我正在尝试学习Powershell,我想创建一个可以打开原始PGN的脚本,然后将其重新格式化为如上所示,并可能拉出事件,日期,白人播放器,黑人播放器和结果。然后对其进行格式化,以便在每次移动后插入一个新行。然后输出一个用[pgn][/pgn]
包围的新文件。
我很失落如何做到这一点。我需要使用正则表达式吗?我知道,一旦我将文件读入Powershell,我就可以像对待数组那样对待它。
输出文件应如下所示:
[pgn][Event "Computer chess game"]
[Date "2015.10.28"]
[White "White Player"]
[Black "Black Player"]
[Result "1-0"]
1. f3 e6
2. g4 Qh4# 1-0 [/pgn]
感谢任何和所有帮助!
答案 0 :(得分:2)
这是将PGN转换为Reddit兼容格式的函数。请注意,目前它不支持每个文件有多个游戏的PGN。
使用此功能,您可以:
Event
,Date
,White
,Black
和Result
函数接受以下参数:
用法示例:
转换文件,输出到屏幕
ConvertPgn-ForReddit -Path .\Foo.pgn
[pgn]
[Event "Computer chess game"]
[Date "2015.10.28"]
[White "White Player"]
[Black "Black Player"]
[Result "1-0"]
1. f3 e6
2. g4 Qh4# 1-0
[/pgn]
转换文件,输出到文件
ConvertPgn-ForReddit -Path .\Foo.pgn -OutFile .\Bar.pgn
转换文件,输出到屏幕,仅保留BlackElo
和Time
标题
ConvertPgn-ForReddit -Path .\Foo.pgn -KeepHeaders BlackElo, Time
[pgn]
[BlackElo "2400"]
[Time "10:39:20"]
1. f3 e6
2. g4 Qh4# 1-0
[/pgn]
function ConvertPgn-ForReddit
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[ValidateScript({
Test-Path $_
})]
[ValidateNotNullOrEmpty()]
[string]$Path,
[Parameter(ValueFromPipelineByPropertyName = $true)]
[string]$OutFile,
[Parameter(ValueFromPipelineByPropertyName = $true)]
[string[]]$KeepHeaders = @('Event', 'Date', 'White', 'Black', 'Result')
)
Process
{
# Get file contents as array of strings
$PgnFile = Get-Content -Path $Path
# Get all "headers", e.g. [Event "Computer chess game"]
$Headers = $PgnFile | Where-Object {$_ -match '\[.*\]'}
# Filter "headers", so they contain only the ones we want
$FilteredHeaders = $KeepHeaders | ForEach-Object {
$currHeader = $_
$Headers | Where-Object {$_ -match "\[$currHeader\s+.*\]"}
}
# Get chess moves
$Moves = $PgnFile | Where-Object {$_ -match '^\d+\.'}
# Split them, remove empty lines if any
$SplittedMoves = $Moves | ForEach-Object {$_ -split '(\d+\.)'} | Where-Object {$_}
# Join splitted chess moves: delimeter + actual move. E.g. "1." + "f3 e6 "
$JoinedMoves = 0..($SplittedMoves.Count - 1) | ForEach-Object {
if([bool]!($_ % 2))
{
'{0} {1}' -f $SplittedMoves[$_], $SplittedMoves[$_+1]
}
}
# Create PGN in Reddit-compatible format
$RedditPgn = '[pgn]', $FilteredHeaders, $JoinedMoves, '[/pgn]'
if($OutFile)
{
# If OutFile is specified, save it
$RedditPgn | Set-Content -Path $OutFile
}
else
{
# If not - just output to the pipeline
$RedditPgn
}
}
}
答案 1 :(得分:-1)
Heyya,
编辑:这不正确,因为我不知道PGN是如何工作的......
这是我的尝试。输入文件pgn.txt
,输出文件converted_pgn.txt
。根据您提供的样品。如果您更改输入文件中的行数或它们的顺序,则会将其分解为多个部分:)。
Get-Content
将从提供的输入文件中生成array
。然后你只需保留你想要的细胞。
为了分开这些动作,我去了Split
空格。
所有这一切都没有真正完善,你可以用正则表达式做更好的工作,如果一切都要改变,输入方式。
#$pgn = Get-Content "pgn.txt"
#this will give us an array like below
$pgn = "--------------------------------------",
"[Event `"Computer chess game`"]",
"[Date `"2015.10.28`"]",
"[Round `"?`"]",
"[White `"White Player`"]",
"[Black `"Black Player`"]",
"[Result `"1-0`"]",
"[BlackElo `"2400`"]",
"[ECO `"A25`"]",
"[Opening `"English`"]",
"[Time `"10:39:20`"]",
"[Variation `"Closed`"]",
"[WhiteElo `"2400`"]",
"[Termination `"normal`"]",
"[PlyCount `"63`"]",
"[WhiteType `"human`"]",
"[BlackType `"human`"]",
"1. f3 e6 2. g4 Qh4# 1-0",
"-------------------------------"
$moves = $pgn[17].Split(" ")
$m1 = $moves[0] + " " + $moves[1] + " " + $moves[2]
$m2 = $moves[3] + " " + $moves[4] + " " + $moves[5] + " " + $moves[6]
"[pgn]$($pgn[1])",$pgn[2],$pgn[4],$pgn[5],$pgn[6],$m1,"$m2 [/pgn]" | Out-File "converted_pgn.txt"
输出:
[pgn][Event "Computer chess game"]
[Date "2015.10.28"]
[White "White Player"]
[Black "Black Player"]
[Result "1-0"]
1. f3 e6
2. g4 Qh4# 1-0 [/pgn]