Released as 20230522 ('Charles')

This commit is contained in:
Ole Tange 2023-05-22 22:27:10 +02:00
parent 268507ff25
commit 7aa3453bdd
21 changed files with 393 additions and 75 deletions

25
NEWS
View file

@ -1,3 +1,28 @@
20230522
New in this release:
* Bug fixes and man page updates.
News about GNU Parallel:
* Introduction to parallel computing https://youtu.be/fvrHXV8yqU4?t=2874
* Script for summarizing GNU parallel joblog file https://github.com/gavinmdouglas/parallel_joblog_summary
* How to copy a single file to multiple directories in Linux or Unix https://www.cyberciti.biz/faq/linux-unix-copy-a-file-to-multiple-directories-using-cp-command/
* Search in your Jupyter notebooks from the CLI, fast. https://dev.to/attilavm/search-in-your-jupyter-notebooks-from-the-cli-fast-1408
* Parallel Job Orchestration with GNU Parallel https://www.youtube.com/watch?v=2tVpUfND3LI
* Optional Individual Submission 4 Job Handling 20266001 - GNU Parallel https://www.youtube.com/watch?v=eC_RPuFCcU8
* DOE Cross-facility Workflows Training - April 12, 2023 https://www.youtube.com/watch?v=Ke3sirM-aQQ
* How to run MiXCR 4.x on multiple patient samples using GNU Parallel https://www.youtube.com/watch?v=OXg-WHlB_dk
20230422
New in this release:

24
README
View file

@ -57,11 +57,11 @@ document.
Full installation of GNU Parallel is as simple as:
wget https://ftpmirror.gnu.org/parallel/parallel-20230422.tar.bz2
wget https://ftpmirror.gnu.org/parallel/parallel-20230422.tar.bz2.sig
gpg parallel-20230422.tar.bz2.sig
bzip2 -dc parallel-20230422.tar.bz2 | tar xvf -
cd parallel-20230422
wget https://ftpmirror.gnu.org/parallel/parallel-20230522.tar.bz2
wget https://ftpmirror.gnu.org/parallel/parallel-20230522.tar.bz2.sig
gpg parallel-20230522.tar.bz2.sig
bzip2 -dc parallel-20230522.tar.bz2 | tar xvf -
cd parallel-20230522
./configure && make && sudo make install
@ -70,11 +70,11 @@ Full installation of GNU Parallel is as simple as:
If you are not root you can add ~/bin to your path and install in
~/bin and ~/share:
wget https://ftpmirror.gnu.org/parallel/parallel-20230422.tar.bz2
wget https://ftpmirror.gnu.org/parallel/parallel-20230422.tar.bz2.sig
gpg parallel-20230422.tar.bz2.sig
bzip2 -dc parallel-20230422.tar.bz2 | tar xvf -
cd parallel-20230422
wget https://ftpmirror.gnu.org/parallel/parallel-20230522.tar.bz2
wget https://ftpmirror.gnu.org/parallel/parallel-20230522.tar.bz2.sig
gpg parallel-20230522.tar.bz2.sig
bzip2 -dc parallel-20230522.tar.bz2 | tar xvf -
cd parallel-20230522
./configure --prefix=$HOME && make && make install
Or if your system lacks 'make' you can simply copy src/parallel
@ -122,8 +122,8 @@ will love you for it.
When using programs that use GNU Parallel to process data for
publication please cite:
Tange, O. (2023, April 22). GNU Parallel 20230422 ('Grand Jury').
Zenodo. https://doi.org/10.5281/zenodo.7855617
Tange, O. (2023, May 22). GNU Parallel 20230522 ('Charles').
Zenodo. https://doi.org/10.5281/zenodo.7958356
Copyright (C) 2007-2022 Ole Tange, http://ole.tange.dk and Free
Software Foundation, Inc.

20
configure vendored
View file

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for parallel 20230422.
# Generated by GNU Autoconf 2.71 for parallel 20230522.
#
# Report bugs to <bug-parallel@gnu.org>.
#
@ -610,8 +610,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='parallel'
PACKAGE_TARNAME='parallel'
PACKAGE_VERSION='20230422'
PACKAGE_STRING='parallel 20230422'
PACKAGE_VERSION='20230522'
PACKAGE_STRING='parallel 20230522'
PACKAGE_BUGREPORT='bug-parallel@gnu.org'
PACKAGE_URL=''
@ -1246,7 +1246,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures parallel 20230422 to adapt to many kinds of systems.
\`configure' configures parallel 20230522 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1313,7 +1313,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of parallel 20230422:";;
short | recursive ) echo "Configuration of parallel 20230522:";;
esac
cat <<\_ACEOF
@ -1390,7 +1390,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
parallel configure 20230422
parallel configure 20230522
generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc.
@ -1427,7 +1427,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by parallel $as_me 20230422, which was
It was created by parallel $as_me 20230522, which was
generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw
@ -2379,7 +2379,7 @@ fi
# Define the identity of the package.
PACKAGE='parallel'
VERSION='20230422'
VERSION='20230522'
printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h
@ -3026,7 +3026,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by parallel $as_me 20230422, which was
This file was extended by parallel $as_me 20230522, which was
generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -3090,7 +3090,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\
parallel config.status 20230422
parallel config.status 20230522
configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\"

View file

@ -1,4 +1,4 @@
AC_INIT([parallel],[20230422],[bug-parallel@gnu.org])
AC_INIT([parallel],[20230522],[bug-parallel@gnu.org])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([

View file

@ -5,9 +5,6 @@
Quote of the month:
Recently learned how to use GNU parallel (from ChatGPT, no less!) and I've gone mad with power
-- Mark, Anthropomorphic Anuran @reject_resubmit@twitter
gnu parallel is actually like. really easy
-- tom (era) @slimefiend@twitter
@ -231,6 +228,9 @@ https://negfeedback.blogspot.com/2020/05/indispensable-command-line-tools.html
=== Used ===
Recently learned how to use GNU parallel (from ChatGPT, no less!) and I've gone mad with power
-- Mark, Anthropomorphic Anuran @reject_resubmit@twitter
parallel might be one of the best utilities out there
-- @ThePrimeagen ThePrimeagen

View file

@ -263,17 +263,18 @@ from:tange@gnu.org
to:parallel@gnu.org, bug-parallel@gnu.org
stable-bcc: Jesse Alama <jessealama@fastmail.fm>
Subject: GNU Parallel 20230522 ('Charles<<>>') released
Subject: GNU Parallel 20230522 ('Charles') released [stable]
GNU Parallel 20230522 ('<<>>') has been released. It is available for download at: lbry://@GnuParallel:4
GNU Parallel 20230522 ('Charles') has been released. It is available for download at: lbry://@GnuParallel:4
Quote of the month:
<<>>
Recently learned how to use GNU parallel (from ChatGPT, no less!) and I've gone mad with power
-- Mark, Anthropomorphic Anuran @reject_resubmit@twitter
New in this release:
<<>>
* No new features. This is a candidate for a stable release.
* Bug fixes and man page updates.
@ -283,19 +284,17 @@ News about GNU Parallel:
* Script for summarizing GNU parallel joblog file https://github.com/gavinmdouglas/parallel_joblog_summary
https://www.cyberciti.biz/faq/linux-unix-copy-a-file-to-multiple-directories-using-cp-command/
https://dev.to/attilavm/search-in-your-jupyter-notebooks-from-the-cli-fast-1408
* How to copy a single file to multiple directories in Linux or Unix https://www.cyberciti.biz/faq/linux-unix-copy-a-file-to-multiple-directories-using-cp-command/
https://www.youtube.com/watch?v=2tVpUfND3LI
https://www.youtube.com/watch?v=eC_RPuFCcU8
https://www.youtube.com/watch?v=3vFxDqgcdVI
* Search in your Jupyter notebooks from the CLI, fast. https://dev.to/attilavm/search-in-your-jupyter-notebooks-from-the-cli-fast-1408
https://www.youtube.com/watch?v=Ke3sirM-aQQ
https://www.youtube.com/watch?v=OXg-WHlB_dk
* Parallel Job Orchestration with GNU Parallel https://www.youtube.com/watch?v=2tVpUfND3LI
<<>>
* Optional Individual Submission 4 Job Handling 20266001 - GNU Parallel https://www.youtube.com/watch?v=eC_RPuFCcU8
* DOE Cross-facility Workflows Training - April 12, 2023 https://www.youtube.com/watch?v=Ke3sirM-aQQ
* How to run MiXCR 4.x on multiple patient samples using GNU Parallel https://www.youtube.com/watch?v=OXg-WHlB_dk
GNU Parallel - For people who live life in the parallel lane.

View file

@ -1,7 +1,7 @@
<directory name="parallel" rev="361" vrev="2" srcmd5="2a7d8bb12a37e2a1df51974e30fcac52">
<entry name="PKGBUILD" md5="7577ce8166ca189fa31d1f9f9dd0aec5" size="1246" mtime="1682193426" />
<entry name="parallel-20230422.tar.bz2" md5="67663e5dd2387bab6367c397b1d8303a" size="2483119" mtime="1682193427" />
<entry name="parallel.spec" md5="c67cb63ddd8b10dfa55d1e01c846a4ce" size="6224" mtime="1682193427" />
<entry name="parallel_20230422.dsc" md5="a994db64fe980a7c2e89b5c32ece2e1e" size="556" mtime="1682193427" />
<entry name="parallel_20230422.tar.gz" md5="0be0cb9baa636daed69ad91214f0c628" size="2762791" mtime="1682193428" />
<directory name="parallel" rev="362" vrev="2" srcmd5="4c35e54a8a572db4bd70dbf4e3cd3e2d">
<entry name="PKGBUILD" md5="bd771f3fadb24d5f4c3847113ecac698" size="1246" mtime="1684784391" />
<entry name="parallel-20230522.tar.bz2" md5="a25c77e65e0e3c269514381c01bdb049" size="2495738" mtime="1684784391" />
<entry name="parallel.spec" md5="e78eb660abc88e51a6bd43e9321b2285" size="6224" mtime="1684784391" />
<entry name="parallel_20230522.dsc" md5="b87ba7da6b01101b2619a9bea59e910b" size="556" mtime="1684784391" />
<entry name="parallel_20230522.tar.gz" md5="1820fdc6713245eb1122fdf27f552892" size="2777335" mtime="1684784392" />
</directory>

View file

@ -1,7 +1,7 @@
Summary: Shell tool for executing jobs in parallel
Name: parallel
Version: 20230422
Version: 20230522
Release: 2.1
License: GPL-3.0-or-later
Group: Productivity/File utilities

View file

@ -393,7 +393,7 @@ _parset_main() {
fi
if [ "$_parset_NAME" = "--version" ] ; then
# shellcheck disable=SC2006
echo "parset 20230423 (GNU parallel `parallel --minversion 1`)"
echo "parset 20230522 (GNU parallel `parallel --minversion 1`)"
echo "Copyright (C) 2007-2023 Ole Tange, http://ole.tange.dk and Free Software"
echo "Foundation, Inc."
echo "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>"

View file

@ -395,7 +395,7 @@ _parset_main() {
fi
if [ "$_parset_NAME" = "--version" ] ; then
# shellcheck disable=SC2006
echo "parset 20230423 (GNU parallel `parallel --minversion 1`)"
echo "parset 20230522 (GNU parallel `parallel --minversion 1`)"
echo "Copyright (C) 2007-2023 Ole Tange, http://ole.tange.dk and Free Software"
echo "Foundation, Inc."
echo "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>"

View file

@ -393,7 +393,7 @@ _parset_main() {
fi
if [ "$_parset_NAME" = "--version" ] ; then
# shellcheck disable=SC2006
echo "parset 20230423 (GNU parallel `parallel --minversion 1`)"
echo "parset 20230522 (GNU parallel `parallel --minversion 1`)"
echo "Copyright (C) 2007-2023 Ole Tange, http://ole.tange.dk and Free Software"
echo "Foundation, Inc."
echo "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>"

View file

@ -376,7 +376,7 @@ _parset_main() {
fi
if [ "$_parset_NAME" = "--version" ] ; then
# shellcheck disable=SC2006
echo "parset 20230423 (GNU parallel `parallel --minversion 1`)"
echo "parset 20230522 (GNU parallel `parallel --minversion 1`)"
echo "Copyright (C) 2007-2023 Ole Tange, http://ole.tange.dk and Free Software"
echo "Foundation, Inc."
echo "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>"

View file

@ -378,7 +378,7 @@ _parset_main() {
fi
if [ "$_parset_NAME" = "--version" ] ; then
# shellcheck disable=SC2006
echo "parset 20230423 (GNU parallel `parallel --minversion 1`)"
echo "parset 20230522 (GNU parallel `parallel --minversion 1`)"
echo "Copyright (C) 2007-2023 Ole Tange, http://ole.tange.dk and Free Software"
echo "Foundation, Inc."
echo "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>"

View file

@ -393,7 +393,7 @@ _parset_main() {
fi
if [ "$_parset_NAME" = "--version" ] ; then
# shellcheck disable=SC2006
echo "parset 20230423 (GNU parallel `parallel --minversion 1`)"
echo "parset 20230522 (GNU parallel `parallel --minversion 1`)"
echo "Copyright (C) 2007-2023 Ole Tange, http://ole.tange.dk and Free Software"
echo "Foundation, Inc."
echo "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>"

View file

@ -368,7 +368,7 @@ _parset_main() {
fi
if [ "$_parset_NAME" = "--version" ] ; then
# shellcheck disable=SC2006
echo "parset 20230423 (GNU parallel `parallel --minversion 1`)"
echo "parset 20230522 (GNU parallel `parallel --minversion 1`)"
echo "Copyright (C) 2007-2023 Ole Tange, http://ole.tange.dk and Free Software"
echo "Foundation, Inc."
echo "License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>"

View file

@ -26,7 +26,7 @@
use strict;
use Getopt::Long;
$Global::progname="niceload";
$Global::version = 20230423;
$Global::version = 20230522;
Getopt::Long::Configure("bundling","require_order");
get_options_from_array(\@ARGV) || die_usage();
if($opt::version) {

View file

@ -2799,7 +2799,7 @@ sub check_invalid_option_combinations() {
sub init_globals() {
# Defaults:
$Global::version = 20230423;
$Global::version = 20230522;
$Global::progname = 'parallel';
$::name = "GNU Parallel";
$Global::infinity = 2**31;
@ -5748,8 +5748,8 @@ sub usage() {
"If you use programs that use GNU Parallel to process data for an article in a",
"scientific publication, please cite:",
"",
" Tange, O. (2023, April 22). GNU Parallel 20230422 ('Grand Jury').",
" Zenodo. https://doi.org/10.5281/zenodo.7855617",
" Tange, O. (2023, May 22). GNU Parallel 20230522 ('Charles').",
" Zenodo. https://doi.org/10.5281/zenodo.7958356",
"",
# Before changing these lines, please read
# https://www.gnu.org/software/parallel/parallel_design.html#citation-notice
@ -5781,8 +5781,8 @@ sub citation_notice() {
"If you use programs that use GNU Parallel to process data for an article in a",
"scientific publication, please cite:",
"",
" Tange, O. (2023, April 22). GNU Parallel 20230422 ('Grand Jury').",
" Zenodo. https://doi.org/10.5281/zenodo.7855617",
" Tange, O. (2023, May 22). GNU Parallel 20230522 ('Charles').",
" Zenodo. https://doi.org/10.5281/zenodo.7958356",
"",
# Before changing these line, please read
# https://www.gnu.org/software/parallel/parallel_design.html#citation-notice and
@ -5909,20 +5909,20 @@ sub citation() {
"If you use programs that use GNU Parallel to process data for an article in a",
"scientific publication, please cite:",
"",
"\@software{tange_2023_7855617,",
"\@software{tange_2023_7958356,",
" author = {Tange, Ole},",
" title = {GNU Parallel 20230422 ('Grand Jury')},",
" month = Apr,",
" title = {GNU Parallel 20230522 ('Charles')},",
" month = May,",
" year = 2023,",
" note = {{GNU Parallel is a general parallelizer to run",
" multiple serial command line programs in parallel",
" without changing them.}},",
" publisher = {Zenodo},",
" doi = {10.5281/zenodo.7855617},",
" url = {https://doi.org/10.5281/zenodo.7855617}",
" doi = {10.5281/zenodo.7958356},",
" url = {https://doi.org/10.5281/zenodo.7958356}",
"}",
"",
"(Feel free to use \\nocite{tange_2023_7855617})",
"(Feel free to use \\nocite{tange_2023_7958356})",
"",
# Before changing these lines, please read
# https://www.gnu.org/software/parallel/parallel_design.html#citation-notice and

View file

@ -1562,9 +1562,9 @@ Similar to B<--memfree>.
See also: B<--memfree> B<--load>
=item B<--latest-line> (alpha testing)
=item B<--latest-line> (beta testing)
=item B<--ll> (alpha testing)
=item B<--ll> (beta testing)
Print the lastest line. Each job gets a single line that is updated
with the lastest output from the job.
@ -1834,13 +1834,13 @@ Similar to B<--tty> but does not set B<--jobs> or B<--ungroup>.
See also: B<--tty>
=item B<--output-as-files> (beta testing)
=item B<--output-as-files>
=item B<--outputasfiles> (beta testing)
=item B<--outputasfiles>
=item B<--files> (beta testing)
=item B<--files>
=item B<--files0> (beta testing)
=item B<--files0>
Save output to files.
@ -1892,7 +1892,7 @@ See also: B<--block> B<--block-timeout> B<--recstart> B<--recend>
B<--fifo> B<--cat> B<--pipe-part> B<-N> B<-L> B<--round-robin>
=item B<--pipe-part>
=item B<--pipe-part> (alpha testing)
Pipe parts of a physical file.

View file

@ -137,7 +137,7 @@ GetOptions(
"help" => \$opt::dummy,
) || exit(255);
$Global::progname = ($0 =~ m:(^|/)([^/]+)$:)[1];
$Global::version = 20230423;
$Global::version = 20230522;
if($opt::version) { version(); exit 0; }
# Remove -D and --parallel=N
my @s = (grep { ! /^-D$|^--parallel=\S+$/ }

View file

@ -670,7 +670,7 @@ $Global::Initfile && unlink $Global::Initfile;
exit ($err);
sub parse_options {
$Global::version = 20230423;
$Global::version = 20230522;
$Global::progname = 'sql';
# This must be done first as this may exec myself

View file

@ -0,0 +1,294 @@
package Text::ParseWords;
use strict;
require 5.006;
our $VERSION = "3.27";
use Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(shellwords quotewords nested_quotewords parse_line);
our @EXPORT_OK = qw(old_shellwords);
our $PERL_SINGLE_QUOTE;
sub shellwords {
my (@lines) = @_;
my @allwords;
foreach my $line (@lines) {
$line =~ s/^\s+//;
my @words = parse_line('\s+', 0, $line);
pop @words if (@words and !defined $words[-1]);
return() unless (@words || !length($line));
push(@allwords, @words);
}
return(@allwords);
}
sub quotewords {
my($delim, $keep, @lines) = @_;
my($line, @words, @allwords);
foreach $line (@lines) {
@words = parse_line($delim, $keep, $line);
return() unless (@words || !length($line));
push(@allwords, @words);
}
return(@allwords);
}
sub nested_quotewords {
my($delim, $keep, @lines) = @_;
my($i, @allwords);
for ($i = 0; $i < @lines; $i++) {
@{$allwords[$i]} = parse_line($delim, $keep, $lines[$i]);
return() unless (@{$allwords[$i]} || !length($lines[$i]));
}
return(@allwords);
}
sub parse_line {
my($delimiter, $keep, $line) = @_;
my($word, @pieces);
no warnings 'uninitialized'; # we will be testing undef strings
while (length($line)) {
# This pattern is optimised to be stack conservative on older perls.
# Do not refactor without being careful and testing it on very long strings.
# See Perl bug #42980 for an example of a stack busting input.
$line =~ s/^
(?:
# double quoted string
(") # $quote
((?>[^\\"]*(?:\\.[^\\"]*)*))" # $quoted
| # --OR--
# singe quoted string
(') # $quote
((?>[^\\']*(?:\\.[^\\']*)*))' # $quoted
| # --OR--
# unquoted string
( # $unquoted
(?:\\.|[^\\"'])*?
)
# followed by
( # $delim
\Z(?!\n) # EOL
| # --OR--
(?-x:$delimiter) # delimiter
| # --OR--
(?!^)(?=["']) # a quote
)
)//xs or return; # extended layout
my ($quote, $quoted, $unquoted, $delim) = (($1 ? ($1,$2) : ($3,$4)), $5, $6);
return() unless( defined($quote) || length($unquoted) || length($delim));
if ($keep) {
$quoted = "$quote$quoted$quote";
}
else {
$unquoted =~ s/\\(.)/$1/sg;
if (defined $quote) {
$quoted =~ s/\\(.)/$1/sg if ($quote eq '"');
$quoted =~ s/\\([\\'])/$1/g if ( $PERL_SINGLE_QUOTE && $quote eq "'");
}
}
$word .= substr($line, 0, 0); # leave results tainted
$word .= defined $quote ? $quoted : $unquoted;
if (length($delim)) {
push(@pieces, $word);
push(@pieces, $delim) if ($keep eq 'delimiters');
undef $word;
}
if (!length($line)) {
push(@pieces, $word);
}
}
return(@pieces);
}
sub old_shellwords {
# Usage:
# use ParseWords;
# @words = old_shellwords($line);
# or
# @words = old_shellwords(@lines);
# or
# @words = old_shellwords(); # defaults to $_ (and clobbers it)
no warnings 'uninitialized'; # we will be testing undef strings
local *_ = \join('', @_) if @_;
my (@words, $snippet);
s/\A\s+//;
while ($_ ne '') {
my $field = substr($_, 0, 0); # leave results tainted
for (;;) {
if (s/\A"(([^"\\]|\\.)*)"//s) {
($snippet = $1) =~ s#\\(.)#$1#sg;
}
elsif (/\A"/) {
require Carp;
Carp::carp("Unmatched double quote: $_");
return();
}
elsif (s/\A'(([^'\\]|\\.)*)'//s) {
($snippet = $1) =~ s#\\(.)#$1#sg;
}
elsif (/\A'/) {
require Carp;
Carp::carp("Unmatched single quote: $_");
return();
}
elsif (s/\A\\(.?)//s) {
$snippet = $1;
}
elsif (s/\A([^\s\\'"]+)//) {
$snippet = $1;
}
else {
s/\A\s+//;
last;
}
$field .= $snippet;
}
push(@words, $field);
}
return @words;
}
1;
__END__
=head1 NAME
Text::ParseWords - parse text into an array of tokens or array of arrays
=head1 SYNOPSIS
use Text::ParseWords;
@lists = nested_quotewords($delim, $keep, @lines);
@words = quotewords($delim, $keep, @lines);
@words = shellwords(@lines);
@words = parse_line($delim, $keep, $line);
@words = old_shellwords(@lines); # DEPRECATED!
=head1 DESCRIPTION
The &nested_quotewords() and &quotewords() functions accept a delimiter
(which can be a regular expression)
and a list of lines and then breaks those lines up into a list of
words ignoring delimiters that appear inside quotes. &quotewords()
returns all of the tokens in a single long list, while &nested_quotewords()
returns a list of token lists corresponding to the elements of @lines.
&parse_line() does tokenizing on a single string. The &*quotewords()
functions simply call &parse_line(), so if you're only splitting
one line you can call &parse_line() directly and save a function
call.
The $keep argument is a boolean flag. If true, then the tokens are
split on the specified delimiter, but all other characters (quotes,
backslashes, etc.) are kept in the tokens. If $keep is false then the
&*quotewords() functions remove all quotes and backslashes that are
not themselves backslash-escaped or inside of single quotes (i.e.,
&quotewords() tries to interpret these characters just like the Bourne
shell). NB: these semantics are significantly different from the
original version of this module shipped with Perl 5.000 through 5.004.
As an additional feature, $keep may be the keyword "delimiters" which
causes the functions to preserve the delimiters in each string as
tokens in the token lists, in addition to preserving quote and
backslash characters.
&shellwords() is written as a special case of &quotewords(), and it
does token parsing with whitespace as a delimiter-- similar to most
Unix shells.
=head1 EXAMPLES
The sample program:
use Text::ParseWords;
@words = quotewords('\s+', 0, q{this is "a test" of\ quotewords \"for you});
$i = 0;
foreach (@words) {
print "$i: <$_>\n";
$i++;
}
produces:
0: <this>
1: <is>
2: <a test>
3: <of quotewords>
4: <"for>
5: <you>
demonstrating:
=over 4
=item 0
a simple word
=item 1
multiple spaces are skipped because of our $delim
=item 2
use of quotes to include a space in a word
=item 3
use of a backslash to include a space in a word
=item 4
use of a backslash to remove the special meaning of a double-quote
=item 5
another simple word (note the lack of effect of the
backslashed double-quote)
=back
Replacing C<quotewords('\s+', 0, q{this is...})>
with C<shellwords(q{this is...})>
is a simpler way to accomplish the same thing.
=head1 AUTHORS
Maintainer: Alexandr Ciornii <alexchornyATgmail.com>.
Previous maintainer: Hal Pomeranz <pomeranz@netcom.com>, 1994-1997 (Original
author unknown). Much of the code for &parse_line() (including the
primary regexp) from Joerk Behrends <jbehrends@multimediaproduzenten.de>.
Examples section another documentation provided by John Heidemann
<johnh@ISI.EDU>
Bug reports, patches, and nagging provided by lots of folks-- thanks
everybody! Special thanks to Michael Schwern <schwern@envirolink.org>
for assuring me that a &nested_quotewords() would be useful, and to
Jeff Friedl <jfriedl@yahoo-inc.com> for telling me not to worry about
error-checking (sort of-- you had to be there).
=cut