Adam Wainwright tossed six effective innings and Paul Goldschmidt had two hits and an RBI as the Cardinals won for only the third time in 14 games.
Dylan Floro (2-4), the fifth Miami pitcher, began the eighth with a walk to Dylan Carlson before Goldschmidt singled. With one out, O'Neill hit his second double of the game to score Carlson, who had two singles.
''I've had a couple of chances like that this year and came up a little short,'' said O'Neill, who hiked his batting average to .291. ''I really wanted to put the ball in play there somewhere hard and give Dylan a good chance to score. That was a good one to get. We've been scuffling a little bit and no one hates losing more than we do. We've got to keep scrapping out there.''
Paul DeJong drove in Goldschmidt with a groundout to make it 4-2.
Giovanny Gallegos (4-1) pitched a hitless inning and Alex Reyes retired the side in the ninth for his 17th save.
Miami had won four of five.
The Cardinals tied it 2-all on an RBI single by Goldschmidt in the fifth when St. Louis knocked out 23-year-old rookie starter Braxton Garrett, who went 4 1/3 innings.
''I felt like I had a great start,'' Garrett said. ''I'd like to have kept going. I'm sure that will come with experience. I'd like to go deeper. I'd like to get to seven. I need to be more efficient and get quicker outs.''
Jazz Chisholm Jr. singled with two outs in the third, scoring Jon Berti and Starling Marte, to give Miami a 2-1 lead. Wainwright loaded the bases on a single and two walks after retiring the first two batters.
Chisholm has reached base in 20 of the 22 games he's played since returning from the injured list May 16.
''We had a few innings after that to try and build on the score and we didn't,'' Miami manager Don Mattingly said.
St. Louis scored its first run in the second on a single by Edmundo Sosa.
''I'm happy to contribute in any way to the team,'' Sosa said through a translator.
The 39-year-old Wainwright faced an opposing pitcher with fewer then 10 career appearances for the fourth straight start. He allowed two runs and four hits with six strikeouts, fanning Jorge Alfaro in the fourth for his 1,900th career punchout.
''We have not been playing great ball but I've got a sneaky suspicion that things are going to turn around for us,'' Wainwright said. ''What we just went through I think will help us in the long run. We'll see what we're made of. I know the guys in the clubhouse aren't folding up. I like our chances to come back strong.''
DON'T FORGET TO TOUCH HOME
Sosa made his first start at second base and the move paid off in the second inning. Magneuris Sierra doubled to center and the ball scooted past Carlson. Tommy Edman fielded it and threw to Sosa, who wheeled and fired home. Adam Duvall, who had singled, slid past the plate and catcher Yadier Molina dropped the ball. Duvall tried to touch the plate, but Molina tagged him. After a review, the out call was upheld. ... In the third inning with two outs, O'Neill doubled to left-center. Marte threw to Chisholm and he fired to Alfaro just off the plate. However, Carlson, who led off with a single, missed home plate and Alfaro tagged him out. After a review, the call stood.
''I've never seen two plays like that in the same game,'' Wainwright said. ''That was crazy.''
MOLINA'S PICKOFF PLAY
In the seventh, Molina ended the inning when pinch-hitter John Curtiss struck out trying to bunt and Molina fired a bullet to first, where Sosa snuck in behind Isan Diaz and tagged him out.
''We had a second baseman make a very smart play with Yadi,'' Cardinals manager Mike Shildt said. ''What a heads-up play by Yadi and a great job by Sosa. Guy bunts through it and it's a good time for a back pick. Sosa saw it and Yadi does what he does.''
PLAYER OF THE WEEK
Marte was selected National League player of the week for the first time in his career Monday. He is the first winner for the Marlins since Giancarlo Stanton and Marcell Ozuna were named co-players of the week on Sept. 25, 2017.
RHP Luis Madero's contract was selected from Triple-A Jacksonville to join the Marlins. Madero, 24, made two relief appearances for Miami in May and went to Jacksonville after he was unclaimed on waivers. The rookie had been designated for assignment May 15.
Marlins: INF Jose Devers (right shoulder impingement) was placed on 10-day injured list. Devers exited Sunday's game after irritating his right shoulder. ... INF Brian Anderson (left shoulder subluxation), sidelined since May 25, has been transferred to the 60-day IL.
Cardinals: RHP Kodi Whitley (mid-back spasms) is playing catch and Shildt said Whitley is around four to six days from getting back on a mound.
Marlins: LHP Trevor Rogers (7-3, 2.02 ERA) makes his second career start against the Cardinals on Tuesday night. He lost to St. Louis on April 5.
Cardinals: LHP Kwang Hyun Kim (1-4, 4.05) returns from his second stint on the injured list for his first outing since sustaining a back injury on June 4. He was removed after just three innings because of lower back stiffness and took his fourth straight defeat as Cincinnati connected off him for a pair of homers. Kim missed just one start.
More AP MLB: https://apnews.com/MLB and https://twitter.com/AP-Sports
Copyright 2021 STATS LLC and Associated Press. Any commercial use or distribution without the express written consent of STATS LLC and Associated Press is strictly prohibited.