Fixed bug #43817: Some JP char cause problems in positional replacement string

This commit is contained in:
Ole Tange 2014-12-14 09:44:32 +01:00
parent b867e321e9
commit f2402e1e83
3 changed files with 62 additions and 48 deletions

View file

@ -950,7 +950,7 @@ sub parse_options {
sub init_globals { sub init_globals {
# Defaults: # Defaults:
$Global::version = 20141209; $Global::version = 20141212;
$Global::progname = 'parallel'; $Global::progname = 'parallel';
$Global::infinity = 2**31; $Global::infinity = 2**31;
$Global::debug = 0; $Global::debug = 0;
@ -6866,12 +6866,16 @@ sub replaced {
if(not defined $self->{'replaced'}) { if(not defined $self->{'replaced'}) {
# Don't quote arguments if the input is the full command line # Don't quote arguments if the input is the full command line
my $quote_arg = $Global::noquote ? 0 : not $Global::quoting; my $quote_arg = $Global::noquote ? 0 : not $Global::quoting;
$self->{'replaced'} = $self->replace_placeholders($self->{'command'},$Global::quoting,$quote_arg); $self->{'replaced'} = $self->
replace_placeholders($self->{'command'},$Global::quoting,
$quote_arg);
my $len = length $self->{'replaced'}; my $len = length $self->{'replaced'};
if ($len != $self->len()) { if ($len != $self->len()) {
::debug("length", $len, " != ", $self->len(), " ", $self->{'replaced'}, "\n"); ::debug("length", $len, " != ", $self->len(),
" ", $self->{'replaced'}, "\n");
} else { } else {
::debug("length", $len, " == ", $self->len(), " ", $self->{'replaced'}, "\n"); ::debug("length", $len, " == ", $self->len(),
" ", $self->{'replaced'}, "\n");
} }
} }
return $self->{'replaced'}; return $self->{'replaced'};
@ -6881,6 +6885,7 @@ sub replaced {
my @target; my @target;
my $context_replace; my $context_replace;
my @arg; my @arg;
my $perl_expressions_as_re;
sub fish_out_words_containing_replacement_strings { sub fish_out_words_containing_replacement_strings {
my %word; my %word;
@ -6966,63 +6971,47 @@ sub replaced {
for my $word (@word) { for my $word (@word) {
# word = AB \257< perlexpr \257> CD \257< perlexpr \257> EF # word = AB \257< perlexpr \257> CD \257< perlexpr \257> EF
my $w = $word; ::debug("replace", "Replacing in $word\n");
::debug("replace", "Replacing in $w\n"); my $normal_replace;
# Replace positional arguments
$w =~ s< ([^\s\257]*) # before {=
\257< # {=
(-?\d+) # Position (eg. -2 or 3)
([^\257]*?) # The perl expression
\257> # =}
([^\s\257]*) # after =}
>
{ $1. # Context (pre)
(
$arg[$2 > 0 ? $2-1 : $n+$2] ? # If defined: replace
$arg[$2 > 0 ? $2-1 : $n+$2]->replace($3,$quote_arg,$self)
: "")
.$4 }egx;# Context (post)
::debug("replace", "Positional replaced $word with: $w\n");
if($w !~ /\257/) {
# No more replacement strings in $w: No need to do more
if($quote) {
CORE::push(@{$replace{::shell_quote($word)}}, $w);
} else {
CORE::push(@{$replace{$word}}, $w);
}
next;
}
# for each arg: # for each arg:
# compute replacement for each string
# replace replacement strings with replacement in the word value # replace replacement strings with replacement in the word value
# push to replace word value # push to replace word value
::debug("replace", "Positional done: $w\n"); $perl_expressions_as_re ||=
join("|", map {s/^-?\d+//; "\Q$_\E"} keys %{$self->{'replacecount'}});
for my $arg (@arg) { for my $arg (@arg) {
my $val = $w; my $val = $word;
my $number_of_replacements = 0;
for my $perlexpr (keys %{$self->{'replacecount'}}) {
# Replace {= perl expr =} with value for each arg # Replace {= perl expr =} with value for each arg
$number_of_replacements += $val =~ s{\257<(-?\d+)?($perl_expressions_as_re)\257>}
$val =~ s{\257<\Q$perlexpr\E\257>} {
{$arg ? $arg->replace($perlexpr,$quote_arg,$self) : ""}eg; if($1) {
# Positional replace
# Find the relevant arg and replace it
($arg[$1 > 0 ? $1-1 : $n+$1] ? # If defined: replace
$arg[$1 > 0 ? $1-1 : $n+$1]->
replace($2,$quote_arg,$self)
: "");
} else {
# Normal replace
$normal_replace ||= 1;
($arg ? $arg->replace($2,$quote_arg,$self) : "");
} }
my $ww = $word; }goxe;
if($quote) { if($quote) {
$ww = ::shell_quote_scalar($word); CORE::push(@{$replace{::shell_quote_scalar($word)}},
$val = ::shell_quote_scalar($val); ::shell_quote_scalar($val));
} } else {
if($number_of_replacements) { CORE::push(@{$replace{$word}}, $val);
CORE::push(@{$replace{$ww}}, $val);
} }
# No normal replacements => only run once
$normal_replace or last;
} }
} }
if($quote) { if($quote) {
@target = ::shell_quote(@target); @target = ::shell_quote(@target);
} }
# ::debug("replace", "%replace=",::my_dump(%replace),"\n"); ::debug("replace", "%replace=",::my_dump(%replace),"\n");
if(%replace) { if(%replace) {
# Substitute the replace strings with the replacement values # Substitute the replace strings with the replacement values
# Must be sorted by length if a short word is a substring of a long word # Must be sorted by length if a short word is a substring of a long word

View file

@ -52,4 +52,13 @@ echo '### {} as part of the command'
echo ls /bin/ls | parallel {} echo ls /bin/ls | parallel {}
echo ls /bin/ls | parallel echo ls /bin/ls | parallel
echo '**'
echo '### bug #43817: Some JP char cause problems in positional replacement strings'
parallel -k echo ::: '<27><<3C>>' '<27><1 $_=2<>>' 'ワ'
parallel -k echo {1} ::: '<27><<3C>>' '<27><1 $_=2<>>' 'ワ'
parallel -Xj1 echo ::: '<27><<3C>>' '<27><1 $_=2<>>' 'ワ'
parallel -Xj1 echo {1} ::: '<27><<3C>>' '<27><1 $_=2<>>' 'ワ'
EOF EOF

View file

@ -64,3 +64,19 @@ echo '### {} as part of the command'
/bin/ls /bin/ls
echo ls /bin/ls | parallel echo ls /bin/ls | parallel
/bin/ls /bin/ls
echo '**'
**
echo '### bug #43817: Some JP char cause problems in positional replacement strings'
### bug #43817: Some JP char cause problems in positional replacement strings
parallel -k echo ::: '<27><<3C>>' '<27><1 $_=2<>>' 'ワ'
<EFBFBD><<3C>>
<EFBFBD><1 $_=2<>>
parallel -k echo {1} ::: '<27><<3C>>' '<27><1 $_=2<>>' 'ワ'
<EFBFBD><<3C>>
<EFBFBD><1 $_=2<>>
parallel -Xj1 echo ::: '<27><<3C>>' '<27><1 $_=2<>>' 'ワ'
<EFBFBD><<3C>> <20><1 $_=2<>> ワ
parallel -Xj1 echo {1} ::: '<27><<3C>>' '<27><1 $_=2<>>' 'ワ'
<EFBFBD><<3C>>