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
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
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
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.)
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.
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.