#!/usr/bin/perl # https://perlmonks.org/?node_id=1226189 use strict; use warnings; while( ) { my @queue = $_; while( @queue ) { local $_ = shift @queue; if( /\|([^|,]*(?:,[^|,]*)+)\|/ ) { push @queue, map "$`|$_|$'", split /,/, $1; } else { print; } } } __DATA__ some text FOO | some text BAR | oh , no , commas | some text BAZ | some text QUX some text FOO | some text BAR | single | some text BAZ | some text QUX some text FOO | some text BAR | oh , no , commas | one, two | some text QUX #### some text FOO | some text BAR | oh | some text BAZ | some text QUX some text FOO | some text BAR | no | some text BAZ | some text QUX some text FOO | some text BAR | commas | some text BAZ | some text QUX some text FOO | some text BAR | single | some text BAZ | some text QUX some text FOO | some text BAR | oh | one| some text QUX some text FOO | some text BAR | oh | two | some text QUX some text FOO | some text BAR | no | one| some text QUX some text FOO | some text BAR | no | two | some text QUX some text FOO | some text BAR | commas | one| some text QUX some text FOO | some text BAR | commas | two | some text QUX