user32181: I want to read a PGN file and play those moves on my chess application. For example, the PGN structure that I have to read looks like this:
1. e4 {[%clk 0:01:00]} 1... g6 {[%clk 0:01:00]} 
2. e5 {[%clk 0:00:59.2]} 2... Bg7 {[%clk 0:00:59.9]} 
3. f4 {[%clk 0:00:58.4]} 3... d6 {[%clk 0:00:59.8]}

So the first move is e4 by white. As human I can look at a chess board and tell that the only piece that can go to e4 is the pawn currently on e2.
But how do you know this when reading a PGN file?
I need to feed my chess applications moves like e2-e4. As in, what ever piece is on e2, move it to e4. (By the notation I can at least tell that the piece is a pawn)
So basically I need to know the starting position of the piece e2, and on what square it wants to land, e4.
Is there a way to get this information from a PGN file? The only way I can think of is brute forcing to identify the only piece that can move to the location.

user32059: I'm confused by this statement:

I need to feed my chess applications moves like e2-e4.

Why? Computers that can read pgn files will understand the moves as they are formated.
If you're inputting them manually, the notation works fine too. People play entire games blindfolded on the same notation. As the you go down the list of moves, the next move is played based on the state of the board from the previous move. That is how algebraic lines have always worked.

user30545: You can use a python chess library to parse the moves of a game in a pgn file.
Code
"""
pip install chess
"""

import chess.pgn

def parse_pgn(inpgn):
    with open(inpgn, encoding='utf-8') as h:
        while True:
            game = chess.pgn.read_game(h)
            if game is None:
                break

            for node in game.mainline():
                move = node.move 
                pnode = node.parent
                board = pnode.board()

                move_from_sq = move.from_square
                move_to_sq = move.to_square

                print(board)
                print(board.fen())
                print(f'move: {move}')
                print(f'move_from: {move_from_sq}')
                print(f'move_from_name: {chess.SQUARE_NAMES[move_from_sq]}')
                print(f'move_to: {move_to_sq}')
                print(f'move_to_name: {chess.SQUARE_NAMES[move_to_sq]}')
                print(f'{chess.SQUARE_NAMES[move_from_sq]}-{chess.SQUARE_NAMES[move_to_sq]}')
                print(f'piece: {board.piece_at(move.from_square).symbol()}')
                print()

def main():
    inpgn = 'sample.pgn'
    parse_pgn(inpgn)

main()

sample.pgn
[Result "*"]

1. e4 {[%clk 0:01:00]} 1... g6 {[%clk 0:01:00]} 
2. e5 {[%clk 0:00:59.2]} 2... Bg7 {[%clk 0:00:59.9]} 
3. f4 {[%clk 0:00:58.4]} 3... d6 {[%clk 0:00:59.8]}

Sample output
r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
P P P P P P P P
R N B Q K B N R
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
move: e2e4
move_from: 12
move_from_name: e2
move_to: 28
move_to_name: e4
e2-e4
piece: P

r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . P . . .
. . . . . . . .
P P P P . P P P
R N B Q K B N R
rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1
move: g7g6
move_from: 54
move_from_name: g7
move_to: 46
move_to_name: g6
g7-g6
piece: p

r n b q k b n r
p p p p p p . p
. . . . . . p .
. . . . . . . .
. . . . P . . .
. . . . . . . .
P P P P . P P P
R N B Q K B N R
rnbqkbnr/pppppp1p/6p1/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2
move: e4e5
move_from: 28
move_from_name: e4
move_to: 36
move_to_name: e5
e4-e5
piece: P

r n b q k b n r
p p p p p p . p
. . . . . . p .
. . . . P . . .
. . . . . . . .
. . . . . . . .
P P P P . P P P
R N B Q K B N R
rnbqkbnr/pppppp1p/6p1/4P3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2
move: f8g7
move_from: 61
move_from_name: f8
move_to: 54
move_to_name: g7
f8-g7
piece: b

r n b q k . n r
p p p p p p b p
. . . . . . p .
. . . . P . . .
. . . . . . . .
. . . . . . . .
P P P P . P P P
R N B Q K B N R
rnbqk1nr/ppppppbp/6p1/4P3/8/8/PPPP1PPP/RNBQKBNR w KQkq - 1 3
move: f2f4
move_from: 13
move_from_name: f2
move_to: 29
move_to_name: f4
f2-f4
piece: P

r n b q k . n r
p p p p p p b p
. . . . . . p .
. . . . P . . .
. . . . . P . .
. . . . . . . .
P P P P . . P P
R N B Q K B N R
rnbqk1nr/ppppppbp/6p1/4P3/5P2/8/PPPP2PP/RNBQKBNR b KQkq - 0 3
move: d7d6
move_from: 51
move_from_name: d7
move_to: 43
move_to_name: d6
d7-d6
piece: p

Square 0 starts at lower left corner of the board or square a1.

32181: <p>I want to read a PGN file and play those moves on my chess application. For example, the PGN structure that I have to read looks like this:</p>
<pre><code>1. e4 {[%clk 0:01:00]} 1... g6 {[%clk 0:01:00]} 
2. e5 {[%clk 0:00:59.2]} 2... Bg7 {[%clk 0:00:59.9]} 
3. f4 {[%clk 0:00:58.4]} 3... d6 {[%clk 0:00:59.8]}
</code></pre>
<p>So the first move is <code>e4</code> by white. As human I can look at a chess board and tell that the only piece that can go to <code>e4</code> is the pawn currently on <code>e2</code>.</p>
<p>But how do you know this when reading a PGN file?</p>
<p>I need to feed my chess applications moves like <code>e2-e4</code>. As in, what ever piece is on <code>e2</code>, move it to <code>e4</code>. (By the notation I can at least tell that the piece is a pawn)</p>
<p>So basically I need to know the starting position of the piece <code>e2</code>, and on what square it wants to land, <code>e4</code>.</p>
<p>Is there a way to get this information from a PGN file? The only way I can think of is brute forcing to identify the only piece that can move to the location.</p>
 32059: <p>I'm confused by this statement:</p>
<blockquote>
<p>I need to feed my chess applications moves like e2-e4.</p>
</blockquote>
<p>Why? Computers that can read pgn files will understand the moves as they are formated.</p>
<p>If you're inputting them manually, the notation works fine too. People play entire games blindfolded on the same notation. As the you go down the list of moves, the next move is played based on the state of the board from the previous move. That is how algebraic lines have always worked.</p>
 30545: <p>You can use a <a href="https://python-chess.readthedocs.io/en/latest/" rel="nofollow noreferrer">python chess library</a> to parse the moves of a game in a pgn file.</p>
<p><strong>Code</strong></p>
<pre><code>&quot;&quot;&quot;
pip install chess
&quot;&quot;&quot;

import chess.pgn

def parse_pgn(inpgn):
    with open(inpgn, encoding='utf-8') as h:
        while True:
            game = chess.pgn.read_game(h)
            if game is None:
                break

            for node in game.mainline():
                move = node.move 
                pnode = node.parent
                board = pnode.board()

                move_from_sq = move.from_square
                move_to_sq = move.to_square

                print(board)
                print(board.fen())
                print(f'move: {move}')
                print(f'move_from: {move_from_sq}')
                print(f'move_from_name: {chess.SQUARE_NAMES[move_from_sq]}')
                print(f'move_to: {move_to_sq}')
                print(f'move_to_name: {chess.SQUARE_NAMES[move_to_sq]}')
                print(f'{chess.SQUARE_NAMES[move_from_sq]}-{chess.SQUARE_NAMES[move_to_sq]}')
                print(f'piece: {board.piece_at(move.from_square).symbol()}')
                print()

def main():
    inpgn = 'sample.pgn'
    parse_pgn(inpgn)

main()
</code></pre>
<p><strong>sample.pgn</strong></p>
<pre><code>[Result &quot;*&quot;]

1. e4 {[%clk 0:01:00]} 1... g6 {[%clk 0:01:00]} 
2. e5 {[%clk 0:00:59.2]} 2... Bg7 {[%clk 0:00:59.9]} 
3. f4 {[%clk 0:00:58.4]} 3... d6 {[%clk 0:00:59.8]}
</code></pre>
<p><strong>Sample output</strong></p>
<pre><code>r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
P P P P P P P P
R N B Q K B N R
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
move: e2e4
move_from: 12
move_from_name: e2
move_to: 28
move_to_name: e4
e2-e4
piece: P

r n b q k b n r
p p p p p p p p
. . . . . . . .
. . . . . . . .
. . . . P . . .
. . . . . . . .
P P P P . P P P
R N B Q K B N R
rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1
move: g7g6
move_from: 54
move_from_name: g7
move_to: 46
move_to_name: g6
g7-g6
piece: p

r n b q k b n r
p p p p p p . p
. . . . . . p .
. . . . . . . .
. . . . P . . .
. . . . . . . .
P P P P . P P P
R N B Q K B N R
rnbqkbnr/pppppp1p/6p1/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2
move: e4e5
move_from: 28
move_from_name: e4
move_to: 36
move_to_name: e5
e4-e5
piece: P

r n b q k b n r
p p p p p p . p
. . . . . . p .
. . . . P . . .
. . . . . . . .
. . . . . . . .
P P P P . P P P
R N B Q K B N R
rnbqkbnr/pppppp1p/6p1/4P3/8/8/PPPP1PPP/RNBQKBNR b KQkq - 0 2
move: f8g7
move_from: 61
move_from_name: f8
move_to: 54
move_to_name: g7
f8-g7
piece: b

r n b q k . n r
p p p p p p b p
. . . . . . p .
. . . . P . . .
. . . . . . . .
. . . . . . . .
P P P P . P P P
R N B Q K B N R
rnbqk1nr/ppppppbp/6p1/4P3/8/8/PPPP1PPP/RNBQKBNR w KQkq - 1 3
move: f2f4
move_from: 13
move_from_name: f2
move_to: 29
move_to_name: f4
f2-f4
piece: P

r n b q k . n r
p p p p p p b p
. . . . . . p .
. . . . P . . .
. . . . . P . .
. . . . . . . .
P P P P . . P P
R N B Q K B N R
rnbqk1nr/ppppppbp/6p1/4P3/5P2/8/PPPP2PP/RNBQKBNR b KQkq - 0 3
move: d7d6
move_from: 51
move_from_name: d7
move_to: 43
move_to_name: d6
d7-d6
piece: p
</code></pre>
<p>Square 0 starts at lower left corner of the board or square a1.</p>
