Can someome help me to run the command below. I also tried to escape the single quotes but no luck.
perl -pi.bak -e 's/Object\.prototype\.myString='q'//' myfile.html
The problem is not with Perl, but with your shell. To see what's happening, try this:
$ echo 's/Object\.prototype\.myString='q'//'
s/Object\.prototype\.myString=q//
To make it work, you can replace each single quote with '\'', like this:
$ echo 's/Object\.prototype\.myString='\''q'\''//'
s/Object\.prototype\.myString='q'//
or you can save a few characters by writing just:
$ echo 's/Object\.prototype\.myString='\'q\''//'
s/Object\.prototype\.myString='q'//
or even just:
$ echo 's/Object\.prototype\.myString='\'q\'//
s/Object\.prototype\.myString='q'//
or even:
$ echo s/Object\\.prototype\\.myString=\'q\'//
s/Object\.prototype\.myString='q'//
Double quotes, as suggested by mu is too short, will work here too, but can cause unwanted surprises in other situations, since many characters commonly found in Perl code, like $, ! and \, have special meaning to the shell even inside double quotes.
Of course, an alternative solution is to replace the single quotes in your regexp with the octal or hex codes \047 or \x27 instead:
$ perl -pi.bak -e 's/Object\.prototype\.myString=\x27q\x27//' myfile.html
Double quotes should work:
perl -pi.bak -e "s/Object\.prototype\.myString='q'//" myfile.html
You may or may not want a g modifier on that regex. And you'll probably want to do a diff after to make sure you didn't mangle the HTML.
Related
I tried to do the following command in bash:
ls -1 | sed s/\(.*\)/"\1"/
which is add double quotes around each output of ls, but the result shows
sed: 1: "s/(.*)/\1/": \1 not defined in the RE
after I add single quotes around the regular expression, I got the right result. the right one is:
ls -1 | sed 's/\(.*\)/"\1"/'
theocratically I do not need the outer quotes right? any one has the same experience?
Single quotes are used to disable shell parsing of various sequences including backslash escapes. If you don't use them, your sequences like \( are passed to sed as (. You may check that by adding echo to the beginning of your command.
Sending the command to echo will show you what sed sees
$ echo sed s/\(.*\)/"\1"/
sed
Hmm, the sed script disappeared altogether. The exposed "*" is forcing the shell to try to match files. Let's disable that:
$ set -f
$ echo sed s/\(.*\)/"\1"/
sed s/(.*)/\1/
The shell ate the quotes and the backslashes. Quoting the sed script:
$ echo sed 's/\(.*\)/"\1"/'
sed s/\(.*\)/"\1"/
That gives the right result, sed will see the script you want to give it. How can we do that without quotes
$ echo sed s/\\\(.\*\\\)/\"\\1\"/
sed s/\(.*\)/"\1"/
And that's ugly.
I want to convert the CSV with double quotes into OpenCSV (no double quotes and comma is escaped with backslash) using unix utilities SED or AWK. I do find examples with perl or java online, but i am looking for one which is simply done using basic SED or AWK.
Not sure about OpenCSV standards, but going by your description you can use this to do a find and replace using SED.
sed -i -e 's/FINDME/REPLACEWITH/g' folder/file.csv
Multiple find/replace can be separated by a semi-colon ;. -i edits a file in place and -e runs a script.
So for your particular example, backslashes and commas make it a little difficult, but this should work:
sed -i -e 's/"/'\''/g;s/,/\\,/g' file.csv
From your description, this might be what you are after:
awk -F'" *, *"|^ *"|" *$' '{a="";for(i=2;i<=NF-1;i++){gsub(/,/,"\\,",$i); if(a){a=a","$i}else{a=$i}};print a}
A bash example:
awk -F'" *, *"|^ *"|" *$' '{a="";for(i=2;i<=NF-1;i++){gsub(/,/,"\\,",$i); if(a){a=a","$i}else{a=$i}};print a}'<<<$'"a","b",","\n"d", "e" ,",,,"'
a,b,\,
d,e,\,\,\,
I have the following string in my file:
"sequence A$_{0}$B$_{}$C$_{'0}$"
I want to move any single quotes that appear after a $_{ to go before it, i.e.
"sequence A$_{0}$B$_{}$C'$_{0}$"
This is my sed command (using # as a delimiter) for just the part with the quote:
$ echo "$_{'0}$" | sed "s#$_{'#'\$_{#g"
'$_{0}$
So this works. However my text contains strings that shouldn't be matched, e.g.
$ echo "$_{0}$" | sed "s#$_{'#'\$_{#g"
/home/ppatest/texlive/2010/texmf{0}$`
I understand that $_ gives the last argument of previous command. I checked:
$ echo $_
/home/ppatest/texlive/2010/texmf
But I don't understand why $_{' matches "$_{0}$"
Furthermore, I found that to prevent the Unix shell from interpreting the dollar sign as a shell variable, the script should be put in single quotes. But I can't do that as I am also matching on single quotes.
Your current approach uses double quotes in sed to be able to handle the single quotes. However, as you can see, this produces the expansion of $, so that you can end up having broader problems.
What I recommend is to use a sed expression with single quotes. To match and replace single quotes, you need to close the leading ', the enclose the ' within " and then open the expression again:
$ echo "he'llo" | sed 's#'"'"'#X#'
heXllo
In your case:
sed 's#$_{'"'"'#'"'"'$_{#g' file
This way, you keep using single quotes and prevent the expansion of $.
Test
$ cat a
hello $_{'0}$ bye
$_{'0}$
yeah
$ sed 's#$_{'"'"'#'"'"'$_{#g' a
hello '$_{0}$ bye
'$_{0}$
yeah
echo "\$_{'0}\$" | sed "s#\(\$_{\)'#'\1#g"
escape the $ when using double quote
use group avoiding several confusing \$ when possible
use double quote when simple quote are part of the pattern
I use this classic perl one liner to replace strings in multiple files recursively
perl -pi -e 's/oldstring/newstring/g' `grep -irl oldstring *`
But this has failed me as I want to find the string:
'$user->primaryorganisation->id'
and replace with
$user->primaryorganisation->id
I can't seem to escape the string correctly for the line to run successfully.
Any help gratefully received!
Try this one. Lots of escapes. Go with TLPs suggestion and use a source file.
perl -pi -e "s/'\\\$user->primaryorganisation->id'/\\\$user->primaryorganisation->id/g" `grep -irl "'\$user->primaryorganisation->id'" *`
Explanation:
three backslashes: the first two tell the shell to produce a literal backslash; the thrid one escapes the $ for the shell; that makes \$ for Perl, which needs the backslash to escape the variable interpolation
double quotes " to put single quotes ' inside them
one backslash and a dollar \$ for grep so the shell passes on a literal dollar sign
When you want to represent a single quote in a perl but can't because the one-liner uses single quotes itself, you can use \047, the octal code for single quote. So, this should work:
s/\047(\$user->primaryorganisation->id)\047/$1/g
I recommend Minimal Perl by Maher for more-than-you-wanted-to-know about the art of one-lining perl.
To produce
...'...
you can generically use
'...'\''...'
As such,
s/'(\$user->primaryorganisation->id)'/$1/g
becomes
's/'\''(\$user->primaryorganisation->id)'\''/$1/g'
so
find -type f \
-exec perl -i -pe's/'\''(\$user->primaryorganisation->id)'\''/$1/g' {} +
I want to replace (whole string)
$(TOPDIR)/$(OSSCHEMASDIRNAME)
with
/udir/makesh/$(OSSCHEMASDIRNAME)
in a makefile
I tried with
perl -pi.bak -e "s/\$\(TOPDIR\)\/\$\(OSSCHEMASDIRNAME\)/\/udir\/makesh\/\$\(OSSCHEMASDIRNAME\)/g " makefile
but i am getting unmatched parentheses error
You have to "double" escape the dollar sign. Like this:
echo "\$(TOPDIR)/\$(OSSCHEMASDIRNAME)" | perl -p -e "s/\\$\(TOPDIR\)\/\\$\(OSSCHEMASDIRNAME\)/\/udir\/makesh\/\\$\(OSSCHEMASDIRNAME\)/g"
First off, you don't need to use / for regular expressions. They're just canonical. You can use pretty much anything. Thus your code can become (simplify away some \):
perl -pi.bak -e "s|\$\(TOPDIR\)/\$\(OSSCHEMASDIRNAME\)|/udir/makesh/\$\(OSSCHEMASDIRNAME\)|g " makefile
Now to actually address your issue, because you're using " instead of ', the shell attempts to figure out what $\ means which is then replaced with (presumably) nothing. So what you really want is:
perl -p -i.bak -e 's|\$\(TOPDIR\)/\$\(OSSCHEMASDIRNAME\)|/udir/makesh/\$\(OSSCHEMASDIRNAME\)|g' makefile
When in doubt about escaping, you can simply use quotemeta or \Q ... \E.
perl -pe 's#\Q$(TOPDIR)\E(?=/\Q$(OSSCHEMASDIRNAME)\E)#/udir/makesh#;'
Note the use of a look-ahead assertion to save us the trouble of repeating the trailing part in the substitution.
A quotemeta solution would be something like:
perl -pe 'BEGIN { $dir = quotemeta(q#$(TOPDIR)/$(OSSCHEMASDIRNAME)#); }
s#$dir#/udir/makesh/$(OSSCHEMASDIRNAME)#;'
Of course, you don't need to use an actual one-liner. When the shell quoting is causing troubles, the simplest option of them all is to write a small source file for your script:
s#\Q$(TOPDIR)\E(?=/\Q$(OSSCHEMASDIRNAME)\E)#/udir/makesh#;
And run with:
perl -p source.pl inputfile