I have a text file, and i want to replace P(blah) with P[blah], everywhere that it exists?
Asked by
joshuav (
17)
July 16th, 2009
importantly, the “blah” between the paren are often different, and of different lengths. sometimes, they include even other pairs of parens. for instance, i might have something like, P(X(t), Y(t)), and also something like P(X(t)). i would like some code that automatically replaces only the OUTER paren with square brackets. thanks.
Observing members:
0
Composing members:
0
13 Answers
Hmm…
I can’t think of any special programs at the moment, You could however do a control – F (or command – F) keyboard shortcut and bring up the “find” box.
In another tab there should be an option “Replace”, type the text to find, then the text that will replace it, hit replace (or replace all).
I’m not sure how that would handle different parenthesis’. I’d make a backup, just in case.
I’d probably write a regular expression to do this.
perl -MRegexp::Common -pi.bak -e ‘s/P\(($RE{balanced}{-parens=>q{()}})\)/P[$1]/g;’ file.txt
This won’t work when the expression is broken across two lines.
cwilbur, yes, the perl script above was exactly what i was looking for. here’s what happened though:
$ perl -MRegexp::Common -pi.bak -e ‘s/P\(($RE{balanced}{-parens=>q{()}})\)/P[$1]/g;’ test.txt
Can’t locate Regexp/Common.pm in @INC (@INC contains: /opt/local/lib/perl5/5.8.8/darwin-2level /opt/local/lib/perl5/5.8.8 /opt/local/lib/perl5/site_perl/5.8.8/darwin-2level /opt/local/lib/perl5/site_perl/5.8.8 /opt/local/lib/perl5/site_perl /opt/local/lib/perl5/vendor_perl/5.8.8/darwin-2level /opt/local/lib/perl5/vendor_perl/5.8.8 /opt/local/lib/perl5/vendor_perl .).
BEGIN failed—compilation aborted.
so, i did a
sudo port install p5-regexp-common
this time, i got no error, but also no change. so, then i created a file called test.txt that contains whose entirety is: P()
running the perl script on that also did nothing. does it work for you? one issue might be that when i copy&paste the above line into terminal (i’m running osx), it replaces the single quotes with ?^?^?. i manually replaced them. can you think of anything? many thanks
It needed refining. The one I gave you would have matched only if there were doubled parentheses: P(()).
perl -MRegexp::Common -pi.bak -e ‘s/P\(([^()]+$RE{balanced}{-parens=>q{()}}?)[^()]+\)/P[$1]/g;’ file.txt
Replace the two + signs with *s – when I put both in, they boldfaced the bit in between.
interesting. so, the one you gave me first indeed works when i have something like “P(())”, but not “P()” or “P(()())”.
the one above doesn’t seem to do anything though. i tried both:
perl -MRegexp::Common -pi.bak -e ‘s/P\(([^()]+$RE{balanced}{-parens=>q{()}}?)[^()]+\)/P[$1]/g;’ file.txt
and
perl -MRegexp::Common -pi.bak -e ‘s/P\(([^()]*s$RE{balanced}{-parens=>q{()}}?)[^()]*s\)/P[$1]/g;’ file.txt
thoughts?
I just copied and pasted it myself, and it works as indicated for me. (Substituting stupid quotes for the smart quotes, of course.)
My file had lines like P(), P(foo), and P(Q(A,B)) in it, and it handled all the cases correctly.
interesting. so, i just tried it again, and
perl -MRegexp::Common -pi.bak -e ‘s/P\(([^()]+$RE{balanced}{-parens=>q{()}}?)[^()]+\)/P[$1]/g;’ file.txt
handles all the case i tried nearly correctly, except that it deletes the last character before the last closing ). ie, if i have
P(ab)
i get
P[a]
thoughts?
i guess a simple solution to this problem would be to first go through and add a space before each ’)’, and then use your perl script, and then remove the space before each ’]’ and ’)’. but i’m guessing you have a better solution :)
ah! When I said “replace the + with *s” I meant replace + with *, not with *s – I was making * plural.
Also, the parenthesis after }}? needs to be after *\) instead.
i see. ok, many thanks for your help! if you care to explain the syntax to me, i’m very curious….
It’s a lot more than I can explain in a quip. You should look for a book called Mastering Regular Expressions—that’s a good place to start.
will do, many thanks :)
ps – i discovered that using vim, the command:
%s/P(\([^[P\$]]*\))/P[\1]/gc
worked as well. i now understand how that works, since i had a bunch of files i needed to do that with, i opened them all up in different tabs, used “tabdo” and then the above, which also worked! one of these days, i’m going to have to learn how to use perl, regexp, etc….
Answer this question
This question is in the General Section. Responses must be helpful and on-topic.