Filename | /usr/lib/x86_64-linux-gnu/perl-base/Text/ParseWords.pm |
Statements | Executed 16 statements in 693µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 7µs | 9µs | BEGIN@3 | Text::ParseWords::
1 | 1 | 1 | 4µs | 14µs | BEGIN@123 | Text::ParseWords::
1 | 1 | 1 | 4µs | 20µs | BEGIN@55 | Text::ParseWords::
1 | 1 | 1 | 4µs | 22µs | BEGIN@4 | Text::ParseWords::
1 | 1 | 1 | 4µs | 9µs | BEGIN@8 | Text::ParseWords::
0 | 0 | 0 | 0s | 0s | nested_quotewords | Text::ParseWords::
0 | 0 | 0 | 0s | 0s | old_shellwords | Text::ParseWords::
0 | 0 | 0 | 0s | 0s | parse_line | Text::ParseWords::
0 | 0 | 0 | 0s | 0s | quotewords | Text::ParseWords::
0 | 0 | 0 | 0s | 0s | shellwords | Text::ParseWords::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Text::ParseWords; | ||||
2 | |||||
3 | 2 | 23µs | 2 | 10µs | # spent 9µs (7+2) within Text::ParseWords::BEGIN@3 which was called:
# once (7µs+2µs) by IPC::Cmd::BEGIN@60 at line 3 # spent 9µs making 1 call to Text::ParseWords::BEGIN@3
# spent 2µs making 1 call to strict::import |
4 | 2 | 28µs | 2 | 40µs | # spent 22µs (4+18) within Text::ParseWords::BEGIN@4 which was called:
# once (4µs+18µs) by IPC::Cmd::BEGIN@60 at line 4 # spent 22µs making 1 call to Text::ParseWords::BEGIN@4
# spent 18µs making 1 call to warnings::import |
5 | 1 | 6µs | require 5.006; | ||
6 | 1 | 300ns | our $VERSION = "3.31"; | ||
7 | |||||
8 | 2 | 216µs | 2 | 15µs | # spent 9µs (4+6) within Text::ParseWords::BEGIN@8 which was called:
# once (4µs+6µs) by IPC::Cmd::BEGIN@60 at line 8 # spent 9µs making 1 call to Text::ParseWords::BEGIN@8
# spent 6µs making 1 call to Exporter::import |
9 | 1 | 5µs | our @ISA = qw(Exporter); | ||
10 | 1 | 500ns | our @EXPORT = qw(shellwords quotewords nested_quotewords parse_line); | ||
11 | 1 | 200ns | our @EXPORT_OK = qw(old_shellwords); | ||
12 | our $PERL_SINGLE_QUOTE; | ||||
13 | |||||
14 | sub shellwords { | ||||
15 | my (@lines) = @_; | ||||
16 | my @allwords; | ||||
17 | |||||
18 | foreach my $line (@lines) { | ||||
19 | $line =~ s/^\s+//; | ||||
20 | my @words = parse_line('\s+', 0, $line); | ||||
21 | pop @words if (@words and !defined $words[-1]); | ||||
22 | return() unless (@words || !length($line)); | ||||
23 | push(@allwords, @words); | ||||
24 | } | ||||
25 | return(@allwords); | ||||
26 | } | ||||
27 | |||||
28 | sub quotewords { | ||||
29 | my($delim, $keep, @lines) = @_; | ||||
30 | my($line, @words, @allwords); | ||||
31 | |||||
32 | foreach $line (@lines) { | ||||
33 | @words = parse_line($delim, $keep, $line); | ||||
34 | return() unless (@words || !length($line)); | ||||
35 | push(@allwords, @words); | ||||
36 | } | ||||
37 | return(@allwords); | ||||
38 | } | ||||
39 | |||||
40 | sub nested_quotewords { | ||||
41 | my($delim, $keep, @lines) = @_; | ||||
42 | my($i, @allwords); | ||||
43 | |||||
44 | for ($i = 0; $i < @lines; $i++) { | ||||
45 | @{$allwords[$i]} = parse_line($delim, $keep, $lines[$i]); | ||||
46 | return() unless (@{$allwords[$i]} || !length($lines[$i])); | ||||
47 | } | ||||
48 | return(@allwords); | ||||
49 | } | ||||
50 | |||||
51 | sub parse_line { | ||||
52 | my($delimiter, $keep, $line) = @_; | ||||
53 | my($word, @pieces); | ||||
54 | |||||
55 | 2 | 186µs | 2 | 36µs | # spent 20µs (4+16) within Text::ParseWords::BEGIN@55 which was called:
# once (4µs+16µs) by IPC::Cmd::BEGIN@60 at line 55 # spent 20µs making 1 call to Text::ParseWords::BEGIN@55
# spent 16µs making 1 call to warnings::unimport |
56 | |||||
57 | while (length($line)) { | ||||
58 | # This pattern is optimised to be stack conservative on older perls. | ||||
59 | # Do not refactor without being careful and testing it on very long strings. | ||||
60 | # See Perl bug #42980 for an example of a stack busting input. | ||||
61 | $line =~ s/^ | ||||
62 | (?: | ||||
63 | # double quoted string | ||||
64 | (") # $quote | ||||
65 | ((?>[^\\"]*(?:\\.[^\\"]*)*))" # $quoted | ||||
66 | | # --OR-- | ||||
67 | # singe quoted string | ||||
68 | (') # $quote | ||||
69 | ((?>[^\\']*(?:\\.[^\\']*)*))' # $quoted | ||||
70 | | # --OR-- | ||||
71 | # unquoted string | ||||
72 | ( # $unquoted | ||||
73 | (?:\\.|[^\\"'])*? | ||||
74 | ) | ||||
75 | # followed by | ||||
76 | ( # $delim | ||||
77 | \Z(?!\n) # EOL | ||||
78 | | # --OR-- | ||||
79 | (?-x:$delimiter) # delimiter | ||||
80 | | # --OR-- | ||||
81 | (?!^)(?=["']) # a quote | ||||
82 | ) | ||||
83 | )//xs or return; # extended layout | ||||
84 | my ($quote, $quoted, $unquoted, $delim) = (($1 ? ($1,$2) : ($3,$4)), $5, $6); | ||||
85 | |||||
86 | return() unless( defined($quote) || length($unquoted) || length($delim)); | ||||
87 | |||||
88 | if ($keep) { | ||||
89 | $quoted = "$quote$quoted$quote"; | ||||
90 | } | ||||
91 | else { | ||||
92 | $unquoted =~ s/\\(.)/$1/sg; | ||||
93 | if (defined $quote) { | ||||
94 | $quoted =~ s/\\(.)/$1/sg if ($quote eq '"'); | ||||
95 | $quoted =~ s/\\([\\'])/$1/g if ( $PERL_SINGLE_QUOTE && $quote eq "'"); | ||||
96 | } | ||||
97 | } | ||||
98 | $word .= substr($line, 0, 0); # leave results tainted | ||||
99 | $word .= defined $quote ? $quoted : $unquoted; | ||||
100 | |||||
101 | if (length($delim)) { | ||||
102 | push(@pieces, $word); | ||||
103 | push(@pieces, $delim) if ($keep eq 'delimiters'); | ||||
104 | undef $word; | ||||
105 | } | ||||
106 | if (!length($line)) { | ||||
107 | push(@pieces, $word); | ||||
108 | } | ||||
109 | } | ||||
110 | return(@pieces); | ||||
111 | } | ||||
112 | |||||
113 | sub old_shellwords { | ||||
114 | |||||
115 | # Usage: | ||||
116 | # use ParseWords; | ||||
117 | # @words = old_shellwords($line); | ||||
118 | # or | ||||
119 | # @words = old_shellwords(@lines); | ||||
120 | # or | ||||
121 | # @words = old_shellwords(); # defaults to $_ (and clobbers it) | ||||
122 | |||||
123 | 2 | 225µs | 2 | 24µs | # spent 14µs (4+10) within Text::ParseWords::BEGIN@123 which was called:
# once (4µs+10µs) by IPC::Cmd::BEGIN@60 at line 123 # spent 14µs making 1 call to Text::ParseWords::BEGIN@123
# spent 10µs making 1 call to warnings::unimport |
124 | local *_ = \join('', @_) if @_; | ||||
125 | my (@words, $snippet); | ||||
126 | |||||
127 | s/\A\s+//; | ||||
128 | while ($_ ne '') { | ||||
129 | my $field = substr($_, 0, 0); # leave results tainted | ||||
130 | for (;;) { | ||||
131 | if (s/\A"(([^"\\]|\\.)*)"//s) { | ||||
132 | ($snippet = $1) =~ s#\\(.)#$1#sg; | ||||
133 | } | ||||
134 | elsif (/\A"/) { | ||||
135 | require Carp; | ||||
136 | Carp::carp("Unmatched double quote: $_"); | ||||
137 | return(); | ||||
138 | } | ||||
139 | elsif (s/\A'(([^'\\]|\\.)*)'//s) { | ||||
140 | ($snippet = $1) =~ s#\\(.)#$1#sg; | ||||
141 | } | ||||
142 | elsif (/\A'/) { | ||||
143 | require Carp; | ||||
144 | Carp::carp("Unmatched single quote: $_"); | ||||
145 | return(); | ||||
146 | } | ||||
147 | elsif (s/\A\\(.?)//s) { | ||||
148 | $snippet = $1; | ||||
149 | } | ||||
150 | elsif (s/\A([^\s\\'"]+)//) { | ||||
151 | $snippet = $1; | ||||
152 | } | ||||
153 | else { | ||||
154 | s/\A\s+//; | ||||
155 | last; | ||||
156 | } | ||||
157 | $field .= $snippet; | ||||
158 | } | ||||
159 | push(@words, $field); | ||||
160 | } | ||||
161 | return @words; | ||||
162 | } | ||||
163 | |||||
164 | 1 | 4µs | 1; | ||
165 | |||||
166 | __END__ |