Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am using Perl with our printing output system. Usually we call perl scripts, but I am just replacing a keyword with another word. In a console and a test file this worked with this one liner:
perl -pi -e "s/KEYWORD1/KEYWORD2"
Now I wanted to use it with our system and it gives me the error that there is no output file created. As I am fairly new to the field of Perl and want to have it used within a one liner, how can i do this?
Thank you very much for your help.
Kind regards
As Shawn mentioned in the comment, you are missing / in the substitution command s///. You are also missing a filename, which is needed for the -i option.
Both of these fail and print a warning and an error:
perl -pi -e "s/KEYWORD1/KEYWORD2" < foo
# or:
cat foo | perl -pi -e "s/KEYWORD1/KEYWORD2"
They print messages:
-i used with no filenames on the command line, reading from STDIN.
Substitution replacement not terminated at -e line 1.
Correct usage:
perl -pi -e 's/KEYWORD1/KEYWORD2/' foo
# or:
perl -pe 's/KEYWORD1/KEYWORD2/' < foo
# or:
another_command | perl -pe 's/KEYWORD1/KEYWORD2/'
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 days ago.
Improve this question
I am trying to store grep output in perl into variable using perl, but not working.
my $out = `grep -oP "Name = \K(.*)" $file)`;
ERR:
you have an extraneous parenthesis at the end )
always use strict; use warnings; you should have seen the error: Unrecognized escape \K passed through
input file:
Name = foobar
code:
perl -Mstrict -we 'print qx(grep -oP "Name = \K(.*)" file)'
Unrecognized escape \K passed through at -e line 1.
Finally:
$ perl -Mstrict -we 'my $out = qx(grep -oP "Name = \\K(.*)" file); print $out'
# ^^
foobar
or a more Perlish way to do it:
perl -nE 'say $& if /Name = \K.*/' file
Problem Background
We have several thousand large (10M<lines) text files of tabular data produced by a windows machine which we need to prepare for upload to a database.
We need to change the file encoding of these files from cp1252 to utf-8, replace any bare Unix LF sequences (i.e. \n) with spaces, then replace the DOS line end sequences ("CR-LF", i.e \r\n) with Unix line end sequences (i.e. \n).
The dos2unix utility is not available for this task.
We initially had a bash function that packaged these operations together using iconv and sed, with iconv doing the encoding and sed dealing with the LF/CRLF sequences. I'm trying to replace part of this bash function with a perl command.
Example Code
Based on some helpful code review, I want to change this function to a perl script.
The author of the code review suggested the following perl to replace CRLF (i.e. "\r\n") with LF ("\n").
perl -g -pe 's/(?<!\r)\n/ /g; s/\r\n/\n/g;'
The explanation for why this is better than what we had previously makes perfect sense, but this line fails for me with:
Unrecognized switch: -g (-h will show valid options).
More interestingly, the author of the code review also suggests it is possible to perform the decode/recode in a perl script, too, but I am completely unsure where to start.
Questions
Please can someone explain why the suggested answer fails with Unrecognized switch: -g (-h will show valid options).?
If it helps, the line is supposed to receive piped input from incov as follows (though I am interested in learning how to use perl to do the redcoding/recoding step, too):
iconv --from-code=CP1252 --to-code=UTF-8 $1$ | \
perl -g -pe 's/(?<!\r)\n/ /g; s/\r\n/\n/g;'
> "$2"
(Highly simplified) example input for testing:
apple|orange|\n|lemon\r\nrasperry|strawberry|mango|\n\r\n
Desired output:
apple|orange| |lemon\nrasperry|strawberry|mango| \n
Perl recently added the command line switch -g as an alias for 'gulp mode' in Perl v5.36.0.
This works in Perl version v5.36.0:
s=$(printf "Line 1\nStill Line 1\r\nLine 2\r\nLine 3\r\n")
perl -g -pe 's/(?<!\r)\n/ /g; s/\r\n/\n/g;' <<<"$s"
Prints:
Line 1 Still Line 1
Line 2
Line 3
But any version of perl earlier than v5.36.0, you would do:
perl -0777 -pe 's/(?<!\r)\n/ /g; s/\r\n/\n/g;' <<<"$s"
# same
BTW, the conversion you are looking for a way easier in this case with awk since it is close to the defaults.
Just do this:
awk -v RS="\r\n" '{gsub(/\n/," ")} 1' <<<"$s"
Line 1 Still Line 1
Line 2
Line 3
Or, if you have a file:
awk -v RS="\r\n" '{gsub(/\n/," ")} 1' file
This is superior to the posted perl solution since the file is processed record be record (each block of text separated by \r\n) versus having the read the entire file into memory.
(On Windows you may need to do awk -v RS="\r\n" -v ORS="\n" '...')
Another note:
You can get similar behavior from Perl by:
Setting the input record separator to the fixed string $/="\r\n" in a BEGIN block;
Use the -l switch so every line has the input record separator removed;
Use tr for speedy replacement of \n with ' ';
Possible set the output record separator, $/="\n", on Windows.
Full command:
perl -lpE 'BEGIN{$/="\r\n"} tr/\n/ /' file
The error message is about the command line switch -g you use in perl -g -pe .... This is not about the switch at the regex - which is valid (but useless since there is only a single \n in a line anyway, and -p reads line by line).
This switch simply does not exist with the perl version you are using. It was only added with perl 5.36, so you are likely using an older version. Try -0777 instead.
This question already has answers here:
Write Dollar sign in sed command pattern inside makefile
(2 answers)
Closed 5 years ago.
I have a simple sed replacement for a text file:
sed -i 's/Temp_3/$t0/g' ./somefile.txt
When I use it in a bash script everything works fine.
However, if I try to use the same line from a makefile,
the $t is (probably) expanded into the empty string
(there is no variable called t in the makefile) and
Temp_3 is replaced with 0. What is the best way to solve this?
Thanks!
What happens is that make first does its substitutions,
in your case $t with nothing, then runs the command.
You can, or should ;), circumvent this problem by changing your command as follows: change $ with $$;
make will substitute the double $ sign with a single one.
sed -i 's/Temp_3/$$t0/g' ./somefile.txt
I have been using Linux env and recently migrated to solaris. Unfortunately one of my bash scripts requires the use of grep with the P switch [ pcre support ] .As Solaris doesnt support the pcre option for grep , I am obliged to find another solution to the problem.And pcregrep seems to have an obvious loop bug and sed -r option is unsupported !
I hope that using perl or nawk will solve the problem on solaris.
I have not yet used perl in my script and am unware neither of its syntax nor the flags.
Since it is pcre , I beleive that a perl scripter can help me out in a matter of minutes. They should match over multiple lines .
Which one would be a better solution in terms of efficiency the awk or the perl solution ?
Thanks for the replies .
These are some grep to perl conversions you might need:
grep -P PATTERN FILE(s) ---> perl -nle 'print if m/PATTERN/' FILE(s)
grep -Po PATTERN FILE(s) ---> perl -nle 'print "$1\n" while m/(PATTERN)/g' FILE(s)
That's my guess as to what you're looking for, if grep -P is out of the question.
Here's a shorty:
grep -P /regex/ ====> perl -ne 'print if /regex/;'
The -n takes each line of the file as input. Each line is put into a special perl variable called $_ as Perl loops through the whole file.
The -e says the Perl program is on the command line instead of passing it a file.
The Perl print command automatically prints out whatever is in $_ if you don't specify for it to print out anything else.
The if /regex/ matches the regular expression against whatever line of your file is in the $_ variable.
I know the perl one liner below is very simple, works and does a global substitution, A for a; but how do I run it in a makefile?
perl -pi -e "s/a/A/g" filename
I have tried (I now think the rest of the post is junk as the shell command does a command line expansion - NOT WHAT I WANT!) The question above still stands!
APP = $(shell perl -pi -e "s/a/A/g" filename)
with and without the following line
EXE = $(APP)
and I always get the following error
make: APP: Command not found
which I assume comes from the line that starts APP
Thanks
If you want to run perl as part of a target's action, you might use
$ cat Makefile
all:
echo abc | perl -pe 's/a/A/g'
$ make
echo abc | perl -pe 's/a/A/g'
Abc
(Note that there's a TAB character before echo.)
Perl's -i option is for editing files in-place, but that will confuse make (unless perhaps you're writing a phony target). A more typical pattern is to make targets from sources. For example:
$ cat Makefile
all: bAr
bAr: bar.in
perl -pe 's/a/A/g' bar.in > bAr
$ cat bar.in
bar
$ make
perl -pe 's/a/A/g' bar.in > bAr
$ cat bAr
bAr
If you let us know what you're trying to do, we'll be able to give you better, more helpful answers.
You should show the smallest possible Makefile which demonstrates your problem, and show how you are calling it. Assuming your Makefile looks something like this, I get the error message. Note that there is a tab character preceding the APP in the all: target.
APP = $(shell date)
all:
APP
Perhaps you meant to do this instead:
APP = $(shell date)
all:
$(APP)
I did not use your perl command because it does not run for me as-is.
Do you really mean to use Perl's substitution operator? perl -pi -e "s/a/A/g"
Here is a link to GNU make documentation.