Inserting a line in text file through perl is failing - perl

I am trying to insert a new row on 2nd line of text file using perl . But it keeps failing.
I am using below command to achieve the same.
perl -ni -e "print; print \"permissibleCars = [ ${part[*]} ]\n\" if $. == 2" query/containerId_count.js
But I keep getting error :--
root#vm-test-001:~/mongosearch# distinct_array=`sed ':a;N;$!ba;s/\n/ /g' output/ontainerId_distinct.txt`
root#vm-test-001:~/mongosearch# declare -a arr=($distinct_array)
root#vm-test-001:~/mongosearch# batchsize=1
root#vm-test-001:~/mongosearch# IFS=,
root#vm-test-001:~/mongosearch# part=( "${arr[#]:i:batchsize}" )
root#vm-test-001:~/mongosearch# echo $part
"C:00000092666270:53882159774"
root#vm-test-001:~/mongosearch# perl -ni -e "print; print \"permissibleCars = [ ${part[*]} ]\n\" if $. == 2" query/containerId_count.js
Bareword found where operator expected at -e line 1, near ""permissibleCars = [ "C"
(Missing operator before C?)
String found where operator expected at -e line 1, near "53882159774" ]\n""
(Missing operator before " ]\n"?)
syntax error at -e line 1, near ""permissibleCars = [ "C"
Illegal octal digit '9' at -e line 1, at end of line
Execution of -e aborted due to compilation errors.
Can you help me with same ?
Regards

Try this:
export PARTS=${part[*]}
perl -lni -e 'print; print "permissibleCars = [".join(",",split/ /,$ENV{PARTS})."]" if $. == 2' query/containerId_count.js
And
In linux platform we should use single quote for one liner. From Perl black book see page number 19 and 20.

Related

I am getting an error : syntax error at -e line 1, at EOF Execution of -e aborted due to compilation errors

The perl script is written to send the data .
and it is throwing the exception as seen :
syntax error at -e line 1, at EOF Execution of -e aborted due to
compilation errors.
Code :
patln=`awk -v dat="$dt" '$0 ~ dat {print NR}' *path of the file where the logs are present*| head -1`
STATUS=$( perl -ne "print if $. >= $patln" *path of the file where the logs are present* | grep TABLE
Don't try to generate Perl code!
# Use an env var.
export patln
perl -ne'print if $. >= $ENV{patln} && /TABLE/' -- "$LOG"
or
# Use an env var (expected to one process only).
patln="$patln" perl -ne'print if $. >= $ENV{patln} && /TABLE/' -- "$LOG"
or
# Use arguments (e.g. using -s)
perl -sne'print if $. >= $patln && /TABLE/' -- -patln="$patln" -- "$LOG"
or
# Perl not even needed here.
tail -n +"$patln" -- "$LOG" | grep TABLE

perl one line script with condition

I have some text file. E.g.
1;one;111
2;two;222
22;two;222
3;three;333
I try to select line that contains "one" using perl-oneliner:
perl -F";" -lane 'print if $F[1]=="one"' forPL.txt
But I get all lines from file.
I don't need use regular expression(reg exp helps in this case), I need exactly match on second field.
Thank you in advance
Use eq for string comparison instead of == which is used for numeric comparison.
perl -F";" -e 'print if $F[1] eq "one" ' test.txt
Edit: As toolic has suggested in his comment, if you had used warnings, you could have easily spot the issue.
$ perl -F";" -e 'use warnings; print if $F[1] == "one" ' test.txt
Argument "one" isn't numeric in numeric eq (==) at -e line 1, <> line 1.
Argument "one" isn't numeric in numeric eq (==) at -e line 1, <> line 1.
1;one;111
Argument "two" isn't numeric in numeric eq (==) at -e line 1, <> line 2.
2;two;222
Argument "two" isn't numeric in numeric eq (==) at -e line 1, <> line 3.
22;two;222
Argument "three" isn't numeric in numeric eq (==) at -e line 1, <> line 4.
3;three;333

Is it possible get a particular argument in printf format in perl in command line?

It's needed to build a string foobar is not foo and not bar.
In printf format %$2s, "2" means a particular argument position.
But it doesn't work in perl:
$ perl -e "printf('%$1s$2s is not %$1s and not %$2s', 'foo', 'bar');"
%2 is not %1 and not %2
My env:
$ perl --version
This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi
(with 29 registered patches, see perl -V for more detail)
Your quoting is off.
perl -E 'say sprintf(q{%1$s%2$s is not %1$s and not %2$s}, "foo", "bar");'
foobar is not foo and not bar
You cannot use double quotes "" for the -e because your shell gets confused. You need single quotes there. But if you use double quotes for the printf pattern with the %1$s syntax, Perl will try to interpolate the $s, which doesn't work. So use a non-quoting q{} or escape the single quotes '' with \'. Or escape the $s.
If you turn on use strict and use warnings you'll see:
$ perl -E 'use strict; use warnings; say sprintf("%1$s%2$s is not %1$s and not %2$s", "foo", "bar");'
Global symbol "$s" requires explicit package name at -e line 1.
Global symbol "$s" requires explicit package name at -e line 1.
Global symbol "$s" requires explicit package name at -e line 1.
Global symbol "$s" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.
That's with single quotes '' for -e and double quotes "" for the pattern.
$ perl -E "use strict; use warnings; say sprintf('%1$s%2$s is not %1$s and not %2$s', 'foo', 'bar');"
Invalid conversion in sprintf: "%1 " at -e line 1.
Invalid conversion in sprintf: "%2" at -e line 1.
%2 is not %1 and not %2
Now the shell tried to interpolate $s because of the double quotes "". So Perl never sees it. It sees the pattern as "%1 %2 is not %1 and not %2", which it cannot understand. (Note that the % will not get interpolated in double quoted strings in Perl).
This works for me on *nix:
perl -e "printf('%s%s is not %1\$s and not %2\$s', 'foo', 'bar');"
See the sprintf documentation, in particular the examples at the very end:
Here are some more examples; be aware that when using an explicit index, the $ may need escaping:
printf "%2\$d %d\n", 12, 34; # will print "34 12\n"
printf "%2\$d %d %d\n", 12, 34; # will print "34 12 34\n"
printf "%3\$d %d %d\n", 12, 34, 56; # will print "56 12 34\n"
printf "%2\$*3\$d %d\n", 12, 34, 3; # will print " 34 12\n"
printf "%*1\$.*f\n", 4, 5, 10; # will print "5.0000\n"
Let's have a look at the program you pass to perl:
$ printf '%s' "printf('%$1s$2s is not %$1s and not %$2s', 'foo', 'bar');"
printf('%ss is not %s and not %s', 'foo', 'bar');
As you can see, there is no $1 or $2 in your program because you improperly built your shell command. Just like Perl interpolates in double-quotes, so do sh and related shells. You should be using single quotes!
perl -e'printf("%\$1s\$2s is not %\$1s and not %\$2s\n", "foo", "bar");'
(I would have suggested switching from '' to q{} inside the Perl program so you wouldn't have to escape the dollar signs, but you need double-quotes for the \n you were missing anyway.)

Bareword found where operator expected at -e line 1, near "9A"

Why am I getting a syntax error?
% perl -ne 'if (/https://([-.0-9A-Za-z]+\.[-0-9A-Za-z]+)/) { print $1 ; }'
Bareword found where operator expected at -e line 1, near "9A"
(Missing operator before A?)
Bareword found where operator expected at -e line 1, near "9A"
(Missing operator before A?)
syntax error at -e line 1, near "9A"
syntax error at -e line 1, near ";}"
Execution of -e aborted due to compilation errors.
If the regex contains slashes, use a different character and the explicit m operator:
perl -ne 'if (m%https://([-.0-9A-Za-z]+\.[-0-9A-Za-z]+)%) { print $1 ; }'
Or:
perl -ne 'print $1 if m{https://([-.0-9A-Za-z]+\.[-0-9A-Za-z]+)}'
You need backslashes in front of the // after https:
perl -ne 'if (/https:\/\/([-.0-9A-Za-z]+\.[-0-9A-Za-z]+)/) { print $1 ; }'
Otherwise it thinks the regex is already over.

Remove newline depending on the format of the next line

I have a special file with this kind of format :
title1
_1 texthere
title2
_2 texthere
I would like all newlines starting with "_" to be placed as a second column to the line before
I tried to do that using sed with this command :
sed 's/_\n/ /g' filename
but it is not giving me what I want to do (doing nothing basically)
Can anyone point me to the right way of doing it ?
Thanks
Try following solution:
In sed the loop is done creating a label (:a), and while not match last line ($!) append next one (N) and return to label a:
:a
$! {
N
b a
}
After this we have the whole file into memory, so do a global substitution for each _ preceded by a newline:
s/\n_/ _/g
p
All together is:
sed -ne ':a ; $! { N ; ba }; s/\n_/ _/g ; p' infile
That yields:
title1 _1 texthere
title2 _2 texthere
If your whole file is like your sample (pairs of lines), then the simplest answer is
paste - - < file
Otherwise
awk '
NR > 1 && /^_/ {printf "%s", OFS}
NR > 1 && !/^_/ {print ""}
{printf "%s", $0}
END {print ""}
' file
This might work for you (GNU sed):
sed ':a;N;s/\n_/ /;ta;P;D' file
This avoids slurping the file into memory.
or:
sed -e ':a' -e 'N' -e 's/\n_/ /' -e 'ta' -e 'P' -e 'D' file
A Perl approach:
perl -00pe 's/\n_/ /g' file
Here, the -00 causes perl to read the file in paragraph mode where a "line" is defined by two consecutive newlines. In your example, it will read the entire file into memory and therefore, a simple global substitution of \n_ with a space will work.
That is not very efficient for very large files though. If your data is too large to fit in memory, use this:
perl -ne 'chomp;
s/^_// ? print "$l " : print "$l\n" if $. > 1;
$l=$_;
END{print "$l\n"}' file
Here, the file is read line by line (-n) and the trailing newline removed from all lines (chomp). At the end of each iteration, the current line is saved as $l ($l=$_). At each line, if the substitution is successful and a _ was removed from the beginning of the line (s/^_//), then the previous line is printed with a space in place of a newline print "$l ". If the substitution failed, the previous line is printed with a newline. The END{} block just prints the final line of the file.