How to surround a string in double quotes - perl

I have a file with the following
firsttext=cat secondtext=dog thirdtext=mouse
and I want it to return this string:
"firsttext=cat" "secondtext=dog" "thirdtext=mouse"
I yave tried this one-liner but it gives me an error.
cat oneline | perl -ne 'print \"$_ \" '
Can't find string terminator '"' anywhere before EOF at -e line 1.
I don't understand the error.Why can't it just add the quotation marks?
Also, if I have a variable in this string, I want it to be interpolated like:
firsttext=${animal} secondtext=${othervar} thirdtext=mouse
Which should output
"firsttext=cat" "secondtext=dog" "thirdtext=mouse"

perl -lne '#f = map qq/"$_"/, split; print "#f";' oneline

What you want is this:
cat oneline | perl -ne 'print join " ", map { qq["$_"] } split'
The -ne option only splits on lines, it won't split on arbitrary whitespace without other options set.

Related

Why does `print "XYZ$_"` work but `print "$_XYZ"` doesn't?

For input abc, the code
perl -ne 'print "XYZ$_"'
prints XYZabc, but after switching the order of $_ and XYZ, i.e.
perl -ne 'print "$_XYZ"'
it prints nothing. Why?
XYZ can be part of a variable name, so $_XYZ is a variable name, rather than $_ followed by a literal XYZ.
You can split the string up:
perl -ne 'print $_ . "XYZ"'
Perl identifiers may contain any letters, digits, or underscore, so you are asking perl to print the value of the variable $_XYZ, which doesn't exist
You may surround the name of the variable with braces { ... } to separate it from any surrounding characters, like so
perl -ne 'print "${_}XYZ"'

Print list on a single line from a pipe

I have a list of PCs and I need to append quotes and commas to each of them so that I can do a SQL query
List example
Row1|PCName|PC1.local
Row2|PCName|PC2.local
Row3|PCName|PC3.local
and I need to get this
"PC1.local", "PC2.local", "PC3.local", ......
Here is what I tried
cat list.txt | awk -F\| '{print $NF}' | perl -e 'while(<>){ print "\"$_\", ";}'
I get this
", "PC1.local
", "PC2.local
", "PC3.local
", "
How can I make those PCs show up in a single line and with the format that I need?
I know using awk or perl might be overkill for this and it could be done using Perl alone or awk alone, but I'm interested in learning how to pipe things to Perl. How can I make Perl print those PC names in the format I need?
How about:
#!/usr/bin/env perl
use strict;
use warnings;
print join ",", map { chomp; '"'.(split /\|/)[2].'"' } <DATA> ;
__DATA__
Row1|PCName|PC1.local
Row2|PCName|PC2.local
Row3|PCName|PC3.local
Output:
"PC1.local","PC2.local","PC3.local"
As a one liner:
perl -e 'print join ",", map { s/\n//; q{"}.(split /\|/)[2].q{"} } <>'
$ awk -F'|' '{printf "%s\"%s\"", (NR>1?", ":""), $3} END{print ""}' file
"PC1.local", "PC2.local", "PC3.local"
with unix toolset
$ cut -d'|' -f3 file | sed 's/.*/"&"/' | paste -s -d,
extract third field, wrap with quotes, join with comma
Here's a Perl one-line solution
$ perl -le 'print join ", ", map { /([^|\s]+)$/ && qq{"$1"} } <>' myfile
output
"PC1.local", "PC2.local", "PC3.local"
#!perl
use strict;
use warnings;
while ( my $line = readline(*STDIN) ) {
chomp $line;
my #machines = split /\|/, $line;
print join(',', map { '"' . $_ . '"' } #machines), "\n";
}
Output:
$ cat list.txt | perl test.pl
"Row1","PCName","PC1.local"
"Row2","PCName","PC2.local"
"Row3","PCName","PC3.local"

How to add blank line after every grep result using Perl?

How to add a blank line after every grep result?
For example, grep -o "xyz" may give something like -
file1:xyz
file2:xyz
file2:xyz2
file3:xyz
I want the output to be like this -
file1:xyz
file2:xyz
file2:xyz2
file3:xyz
I would like to do something like
grep "xyz" | perl (code to add a new line after every grep result)
This is the direct answer to your question:
grep 'xyz' | perl -pe 's/$/\n/'
But this is better:
perl -ne 'print "$_\n" if /xyz/'
EDIT
Ok, after your edit, you want (almost) this:
grep 'xyz' * | perl -pe 'print "\n" if /^([^:]+):/ && ! $seen{$1}++'
If you don’t like the blank line at the beginning, make it:
grep 'xyz' * | perl -pe 'print "\n" if /^([^:]+):/ && ! $seen{$1}++ && $. > 1'
NOTE: This won’t work right on filenames with colons in them. :)½
If you want to use perl, you could do something like
grep "xyz" | perl -p -e 's/(.*)/\1\n/g'
If you want to use sed (where I seem to have gotten better results), you could do something like
grep "xyz" | sed 's/.*/\0\n/g'
This prints a newline after every single line of grep output:
grep "xyz" | perl -pe 'print "\n"'
This prints a newline in between results from different files. (Answering the question as I read it.)
grep 'xyx' * | perl -pe '/(.*?):/; if ($f ne $1) {print "\n"; $f=$1}'
Use a state machine to determine when to print a blank line:
#!/usr/bin/env perl
use strict;
use warnings;
# state variable to determine when to print a blank line
my $prev_file = '';
# change DATA to the appropriate input file handle
while( my $line = <DATA> ){
# did the state change?
if( my ( $file ) = $line =~ m{ \A ([^:]*) \: .*? xyz }msx ){
# blank lines between states
print "\n" if $file ne $prev_file && length $prev_file;
# set the new state
$prev_file = $file;
}
# print every line
print $line;
}
__DATA__
file1:xyz
file2:xyz
file2:xyz2
file3:xyz

'sed' usage in perl script error

I have the following line in a Perl script:
my $temp = `sed 's/ /\n/g' /sys/bus/w1/devices/w1_bus_master1/10-000802415bef/w1_slave | grep t= | sed 's/t=//'`;
Which throws up the error:
"sed: -e expression #1, char 2: unterminated `s' command"
If I run a shell script as below it works fine:
temp1=`sed 's/ /\n/g' /sys/bus/w1/devices/w1_bus_master1/10-000802415bef/w1_slave | grep t= | sed 's/t=//'`
echo $temp1
Anyone got any ideas?
Perl interpretes your \n as a literal newline character. Your command line will therefore look something like this from sed's perspective:
sed s/ /
/g ...
which sed doesn't like. The shell does not interpret it that way.
The proper solution is not to use sed/grep in such a situation at all. Perl is, after all, very, very good at handling text. For example (untested):
use File::Slurp;
my #lines = split m/\n/, map { s/ /\n/g; $_ } scalar(read_file("/sys/bus...));
#lines = map { s/t=//; $_ } grep { m/t=/ } #lines;
Alternatively escape the \n once, e.g. sed 's/ /\\n/g'....
You need to escape the \n in our first regular expression. The backtick-operator in perl thinks it is a control-character and inserts a newline instead of the string \n.
|
V
my $temp = `sed 's/ /\\n/g' /sys/bus/ # ...

How can I use literal single quotes inside the argument to perl's -e?

I try to create a short perl command that creates SQL inserts for my DB based on a text file. However, I am not able to get in the single-quotes used by SQL
perl -pe '$i += 1; chomp; #a = split /\t/; $_ = "INSERT INTO XYZ VALUES($i, \'$a[4]\');\n"'
results in a syntax error near unexpected token `)'
Any ideas?
perl -pe '$i += 1; chomp; #a = split /\t/; $_ = "INSERT INTO XYZ VALUES($i, \047$a[4]\047);\n";'
You need to escape them for the shell, not for Perl. This requires a slightly different syntax. Assuming you're running this under bash, ksh, or similar, then
perl -e 'print "greengrocer'\''s\n"'
should print greengrocer's.
Alternatively, you could insert the character as a hex escape sequence:
perl -e 'print "greengrocer\x27s\n"'
perl -pe "\$i += 1; chomp; #a = split /\t/; \$_ = \"INSERT INTO XYZ VALUES(\$i, '\$a[4]');\n\""
From this page it states for BASH: "A single quote may not occur between single quotes, even when preceded by a backslash.". So use double quotes instead and escape as necessary.
Use the technique #Porculus suggested in his answer:
perl -pe '$i += 1; chomp; #a = split /\t/; $_ = "INSERT INTO XYZ VALUES($i, '\''$a[4]'\'');\n";'
This closes the single-quoted string just before the single quote, then uses an escaped single-quote, then opens a new single-quoted string.
The beauty of this technique is that you can automate it:
sed -e "s/'/'\\\\''/g" -e "s/^/'/" -e "s/$/'/" <<'EOF'
$i += 1; chomp; #a = split /\t/; $_ = "INSERT INTO XYZ VALUES($i, '$a[4]');\n";
EOF
resulting a properly-quoted string you can paste on to the command line :
'$i += 1; chomp; #a = split /\t/; $_ = "INSERT INTO XYZ VALUES($i, '\''$a[4]'\'');\n";'
Or you can make a shell-script for it:
$ cat > quotify
#!/bin/sh
sed -e "s/'/'\\\\''/g" -e "s/^/'/" -e "s/$/'/"
^D
$ chmod +x quotify
$ ./quotify
$i += 1; chomp; #a = split /\t/; $_ = "INSERT INTO XYZ VALUES($i, '$a[4]');\n";
^D
'$i += 1; chomp; #a = split /\t/; $_ = "INSERT INTO XYZ VALUES($i, '\''$a[4]'\'');\n";'
(The above sed firstly replaces each ' with '\'' then puts a ' at the front and back.
Found a work-around by using a | for all single-quote and then in a second perl call replacing this | by a single quote (perl -pe "s/\|/'/g")
perl -pe '$i += 1; chomp; #a = split /\t/; $_ = "INSERT INTO XYZ VALUES($i, |$a[4]|, |$a[5]|, |$a[7]|, |$a[0]|, |$a[1]|, |$a[3]|);\n"' | perl -pe "s/\|/'/g"
Still interested in a better solution.