parallel: Fixed perl expressions spanning multiple lines.

This commit is contained in:
Ole Tange 2018-07-18 14:36:04 +02:00
parent e1e8693797
commit fe92398309
4 changed files with 38 additions and 21 deletions

View file

@ -10001,7 +10001,7 @@ sub replaced {
while($tt =~ s/([^\s\257]* # before {= while($tt =~ s/([^\s\257]* # before {=
(?: (?:
\257< # {= \257< # {=
(?: (?! \257[<>]). )* # The perl expression (?: [^\257]*|[\257][^<>] )* # The perl expression
\257> # =} \257> # =}
[^\s\257]* # after =} [^\s\257]* # after =}
)+)/ /xs) { )+)/ /xs) {
@ -10009,7 +10009,10 @@ sub replaced {
$word{"$1"} ||= 1; $word{"$1"} ||= 1;
} }
} else { } else {
while($tt =~ s/( \257<(?: (?! \257[<>]). )*\257> )//xs) { while($tt =~ s/( \257<(?: # {=
[^\257]*|[\257][^<>] )* # not \257< or \257>
\257> ) # =}
//xs) {
# $1 = \257< perlexpr \257> # $1 = \257< perlexpr \257>
$word{$1} ||= 1; $word{$1} ||= 1;
} }
@ -10148,10 +10151,9 @@ sub new {
my $transfer_files = shift; my $transfer_files = shift;
my $return_files = shift; my $return_files = shift;
my @unget = (); my @unget = ();
my ($count,$posrpl,$perlexpr); my $posrpl;
my ($replacecount_ref, $len_ref); my ($replacecount_ref, $len_ref);
my @command = @$commandref; my @command = @$commandref;
my $dummy = '';
my $seq = 1; my $seq = 1;
# Replace replacement strings with {= perl expr =} # Replace replacement strings with {= perl expr =}
# '{=' 'perlexpr' '=}' => '{= perlexpr =}' # '{=' 'perlexpr' '=}' => '{= perlexpr =}'
@ -10180,7 +10182,7 @@ sub new {
# needed to force matching the shortest {= =} # needed to force matching the shortest {= =}
((?:(?! \Q$Global::parensleft\E|\Q$Global::parensright\E ).)*?) ((?:(?! \Q$Global::parensleft\E|\Q$Global::parensright\E ).)*?)
\Q$Global::parensright\E ] # Match =} \Q$Global::parensright\E ] # Match =}
{\257<$1\257>}gx; {\257<$1\257>}gxs;
for my $rpl (sort { length $b <=> length $a } keys %Global::rpl) { for my $rpl (sort { length $b <=> length $a } keys %Global::rpl) {
# Replace long --rpl's before short ones, as a short may be a # Replace long --rpl's before short ones, as a short may be a
# substring of a long: # substring of a long:
@ -10202,7 +10204,7 @@ sub new {
/xs; /xs;
$grp_regexp ||= ''; $grp_regexp ||= '';
my $rplval = $Global::rpl{$rpl}; my $rplval = $Global::rpl{$rpl};
while(s{( (?: ^|\257> ) (?: (?! \257[<>])(?:.|\n) )*? ) while(s{( (?: ^|\257> ) (?: [^\257]*|[\257][^<>] )*? )
# Don't replace after \257 unless \257> # Don't replace after \257 unless \257>
\Q$prefix\E $grp_regexp \Q$postfix\E} \Q$prefix\E $grp_regexp \Q$postfix\E}
{ {
@ -10235,7 +10237,7 @@ sub new {
# Only do this if the shorthand start with { # Only do this if the shorthand start with {
$prefix=~s/^\{//; $prefix=~s/^\{//;
# Don't replace after \257 unless \257> # Don't replace after \257 unless \257>
while(s{( (?: ^|\257> ) (?: (?! \257[<>]). )*? ) while(s{( (?: ^|\257> ) (?: [^\257]*|[\257][^<>] )*? )
\{(-?\d+) \s* \Q$prefix\E $grp_regexp \Q$postfix\E} \{(-?\d+) \s* \Q$prefix\E $grp_regexp \Q$postfix\E}
{ {
# The start remains the same # The start remains the same
@ -10314,13 +10316,13 @@ sub merge_rpl_parts {
my $s = shift @in; my $s = shift @in;
$_ = $s; $_ = $s;
# Remove matching (right most) parens # Remove matching (right most) parens
while(s/(.*)$l.*?$r/$1/o) {} while(s/(.*)$l.*?$r/$1/os) {}
if(/$l/o) { if(/$l/o) {
# Missing right parens # Missing right parens
while(@in) { while(@in) {
$s .= " ".shift @in; $s .= " ".shift @in;
$_ = $s; $_ = $s;
while(s/(.*)$l.*?$r/$1/o) {} while(s/(.*)$l.*?$r/$1/os) {}
if(not /$l/o) { if(not /$l/o) {
last; last;
} }
@ -10355,7 +10357,7 @@ sub replacement_counts_and_lengths {
my $noncontextlen = 0; my $noncontextlen = 0;
my $contextgroups = 0; my $contextgroups = 0;
for my $c (@cmd) { for my $c (@cmd) {
while($c =~ s/ \257<( (?: (?! \257[<>]). )*?)\257> /\000/xs) { while($c =~ s/ \257<( (?: [^\257]*|[\257][^<>] )*?)\257> /\000/xs) {
# %replacecount = { "perlexpr" => number of times seen } # %replacecount = { "perlexpr" => number of times seen }
# e.g { "s/a/b/" => 2 } # e.g { "s/a/b/" => 2 }
$replacecount{$1}++; $replacecount{$1}++;
@ -10378,7 +10380,7 @@ sub replacement_counts_and_lengths {
# Options that can contain replacement strings # Options that can contain replacement strings
$_ or next; $_ or next;
my $t = $_; my $t = $_;
while($t =~ s/ \257<( (?: (?! \257[<>]). )* )\257> //xs) { while($t =~ s/ \257<( (?: [^\257]*|[\257][^<>] )* )\257> //xs) {
# %replacecount = { "perlexpr" => number of times seen } # %replacecount = { "perlexpr" => number of times seen }
# e.g { "$_++" => 2 } # e.g { "$_++" => 2 }
# But for tagstring we just need to mark it as seen # But for tagstring we just need to mark it as seen

View file

@ -2702,7 +2702,8 @@ To compress all html files using B<gzip> run:
If the file names may contain a newline use B<-0>. Substitute FOO BAR with If the file names may contain a newline use B<-0>. Substitute FOO BAR with
FUBAR in all files in this dir and subdirs: FUBAR in all files in this dir and subdirs:
find . -type f -print0 | parallel -q0 perl -i -pe 's/FOO BAR/FUBAR/g' find . -type f -print0 | \
parallel -q0 perl -i -pe 's/FOO BAR/FUBAR/g'
Note B<-q> is needed because of the space in 'FOO BAR'. Note B<-q> is needed because of the space in 'FOO BAR'.
@ -2777,7 +2778,8 @@ in a directory:
To do it recursively use B<find>: To do it recursively use B<find>:
find . -name '*.jpg' | parallel convert -geometry 120 {} {}_thumb.jpg find . -name '*.jpg' | \
parallel convert -geometry 120 {} {}_thumb.jpg
Notice how the argument has to start with B<{}> as B<{}> will include path Notice how the argument has to start with B<{}> as B<{}> will include path
(e.g. running B<convert -geometry 120 ./foo/bar.jpg (e.g. running B<convert -geometry 120 ./foo/bar.jpg
@ -2787,7 +2789,8 @@ generate files like ./foo/bar.jpg_thumb.jpg.
Use B<{.}> to avoid the extra .jpg in the file name. This command will Use B<{.}> to avoid the extra .jpg in the file name. This command will
make files like ./foo/bar_thumb.jpg: make files like ./foo/bar_thumb.jpg:
find . -name '*.jpg' | parallel convert -geometry 120 {} {.}_thumb.jpg find . -name '*.jpg' | \
parallel convert -geometry 120 {} {.}_thumb.jpg
=head1 EXAMPLE: Substitution and redirection =head1 EXAMPLE: Substitution and redirection
@ -3037,16 +3040,15 @@ downloads 10 videos in parallel.
export url export url
youtube-dl --flat-playlist "$url" | youtube-dl --flat-playlist "$url" |
parallel --tagstring {#} --lb -j10 \ parallel --tagstring {#} --lb -j10 \
LC_ALL= youtube-dl --playlist-start {#} --playlist-end {#} '"$url"' youtube-dl --playlist-start {#} --playlist-end {#} '"$url"'
=head1 EXAMPLE: Copy files as last modified date (ISO8601) with added =head1 EXAMPLE: Prepend last modified date (ISO8601) to file name
random digits
find . | parallel cp {} '../destdir/{= $a=int(10000*rand); $_=pQ($_); parallel mv {} '{= $a=pQ($_); $b=$_;' \
$_=`date -r "$_" +%FT%T"$a"`; chomp; =}' '$_=qx{date -r "$a" +%FT%T}; chomp; $_="$_ $b" =}' ::: *
B<{=> and B<=}> mark a perl expression. B<pQ> quotes the B<{=> and B<=}> mark a perl expression. B<pQ> perl-quotes the
string. B<date +%FT%T> is the date in ISO8601 with time. string. B<date +%FT%T> is the date in ISO8601 with time.
@ -3269,7 +3271,8 @@ repeat the list and use replacement string with a Perl expression that
skips the job if the value from input source 1 is greater than or skips the job if the value from input source 1 is greater than or
equal to the value from input source 2: equal to the value from input source 2:
parallel echo {= 'if($arg[1] ge $arg[2]) { skip() }' =} ::: A B C D ::: A B C D parallel echo {= 'if($arg[1] ge $arg[2]) { skip() }' =} \
::: A B C D ::: A B C D
Or more generally: Or more generally:

View file

@ -825,6 +825,17 @@ par_pipe_recend() {
seq 3 | parallel -k --pipe --recend '' -n 1 xxd seq 3 | parallel -k --pipe --recend '' -n 1 xxd
} }
par_perlexpr_with_newline() {
echo 'Perl expression spanning 2 lines'
cd tmp
touch "Dad's \"famous\" 1' pizza"
# Important with newline in perl expression:
parallel mv {} '{= $a=pQ($_); $b=$_;
$_=qx{date -r "$a" +%FT%T}; chomp; $_="$_ $b" =}' \
::: "Dad's \"famous\" 1' pizza"
rm *"Dad's \"famous\" 1' pizza"
}
export -f $(compgen -A function | grep par_) export -f $(compgen -A function | grep par_)
compgen -A function | grep par_ | sort | compgen -A function | grep par_ | sort |
parallel -j6 --tag -k --joblog +/tmp/jl-`basename $0` '{} 2>&1' parallel -j6 --tag -k --joblog +/tmp/jl-`basename $0` '{} 2>&1'

View file

@ -1386,6 +1386,7 @@ par_parcat_args_stdin OK2
par_parcat_rm bug #51691: parcat --rm remove fifo when opened par_parcat_rm bug #51691: parcat --rm remove fifo when opened
par_parcat_rm OK1 par_parcat_rm OK1
par_parcat_rm OK file removed par_parcat_rm OK file removed
par_perlexpr_with_newline Perl expression spanning 2 lines
par_pipe_no_command ### --pipe without command par_pipe_no_command ### --pipe without command
par_pipe_no_command parallel: Error: --pipe/--pipepart must have a command to pipe into (e.g. 'cat'). par_pipe_no_command parallel: Error: --pipe/--pipepart must have a command to pipe into (e.g. 'cat').
par_pipe_recend bug #54328: --pipe --recend blocks par_pipe_recend bug #54328: --pipe --recend blocks