Reputation: 97
Suppose I have a text file with content like below:
'Jack', is a boy
'Jenny', is a girl
...
...
...
I'd like to use perl in Cli to only capture the names between pairs of single quotes
cat text| perl -ne 'print $1."\n" if/\'(\w+?)\'/'
Above command was what I ran but it didn't work. It seems like "'" messed up with Shell.
I know we have other options like writing a perl script. But given my circumstances, I'd like to find a way to fulfill this in Shell command line.
Please advise.
Upvotes: 1
Views: 136
Reputation: 8398
Here are some methods that do not require manually escaping the perl statement:
(Disclaimer: I'm not sure how robust these are – they haven't been tested extensively)
Cat-in-the-bag technique
perl -ne "$(cat)" text
You will be prompted for input. To terminate cat
, press Ctrl-D.
One shortcoming of this: The perl statement is not reusable. This is addressed by the variation:
$pline=$(cat)
perl -ne "$pline" text
The bash builtin, read
Multiple lines:
read -rd'^[' pline
Single line:
read -r pline
Reads user input into the variable pline
.
The meaning of the switches:
-r
: stop read
from interpreting backslashes (e.g. by default read
interprets \w
as w
)-d
: determines what character ends the read
command.
^[
is the character corresponding to Esc, you insert ^[
by pressing Ctrl-V then Esc.Heredoc and script.
(You said no scripts, but this is quick and dirty, so might as well...)
cat << 'EOF' > scriptonite
print $1 . "\n" if /'(\w+)'/
EOF
then you simply
perl -n scriptonite text
Upvotes: 0
Reputation: 57600
The shell has the interesting property of concatenating quoted strings. Or rather, '...'
or "..."
should not be considered strings, but modifiers for available escapes. The '...'
-surrounded parts of a command have no escapes available. Outside of '...'
, a single quote can be passed as \'
. Together with the concatenating property, we can embed a single quote like
$ perl -E'say "'\''";'
'
into the -e
code. The first '
exits the no-escape zone, \'
is our single quote, and '
re-enters the escapeless zone. What perl
saw was
perl // argv[0]
-Esay "'"; // argv[1]
This would make your command
cat text| perl -ne 'print $1."\n" if/'\''(\w+?)'\''/'
(quotes don't need escaping in regexes), or
cat text| perl -ne "print \$1.qq(\n) if/'(\w+?)'/"
(using double quotes to surround the command, but using qq//
for double quoted strings and escaping the $
sigil to avoid shell variable interpolation).
Upvotes: 3