Perl find & replace - what am I doing wrong?


 
Thread Tools Search this Thread
Top Forums UNIX for Dummies Questions & Answers Perl find & replace - what am I doing wrong?
# 1  
Old 05-29-2013
Perl find & replace - what am I doing wrong?

Hi!
I have a directory full of .plist type files from which I need to delete a line. Not every file contains the line, but of course I'd like to do it recursively. The line which I want to delete is:

Code:
		<string>com.apple.PhotoBooth</string>

and looks like this in its native habitat:

Code:
	<string>748 352 640 526 0 0 1440 878 </string>
	<key>excludedHosts</key>
	<array>
		<string>com.apple.PhotoBooth</string>
		<string>com.apple.iChat</string>
	</array>
	<key>frameworkVersion</key>

Here is what I tried, as well as the error which followed:

Code:
$ perl -pi -e ~/Library/Compositions/Compound\ Eye.qtz 's/<string>com.apple.PhotoBooth</string>\n//g' 
Bareword found where operator expected at -e line 1, near "/Users/rick"
	(Missing operator before rick?)
syntax error at -e line 1, near "/Users/rick"
Execution of -e aborted due to compilation errors.

The interesting thing (to me) is that it seems to be complaining about syntax in the actual directory - /Users/Rick - but I used the abbreviated form - ~/
I didn't really understand what it was complaining about, so I combined all the flags and got a different error.

Code:
$ perl -pie ~/Library/Compositions/Compound\ Eye.qtz 's/<string>com.apple.PhotoBooth</string>\n//g' 
Unrecognized character \xDA; marked by <-- HERE after bplist00<-- HERE near column 9 at ~Library/Compositions/Compound Eye.qtz line 1.

I searched for the string "bplist00" in the file, but cannot find it. I also don't understand why it's talking about columns. I can't make heads or tails of this error. Can anyone tell me what I'm doing wrong? I'll attach one of the files, if that helps.

I'm using Mac OS 10.6.8
bash
# 2  
Old 05-29-2013
Use PlistBuddy to delete the entry:
Code:
/usr/libexec/PlistBuddy -c "Delete :excludedHosts:0" ~/Library/Compositions/Compound\ Eye.qtz

# 3  
Old 05-29-2013
You've badly messed up the command line and the logic.

Try:
Code:
perl -i.old -ne 'print unless m:^\s*<string>com\.apple\.PhotoBooth</string>\s*$:' ~/Library/Compositions/Compound\ Eye.qtz

I recommend (strongly in your case since you don't seem to understand Perl) taking a copy of the input file (which will be done by the command line automatically with an extension of .old).
This User Gave Thanks to elixir_sinari For This Post:
# 4  
Old 05-29-2013
Quote:
Originally Posted by sudon't
The interesting thing (to me) is that it seems to be complaining about syntax in the actual directory - /Users/Rick - but I used the abbreviated form - ~/
No binaries or scripts invoked by a shell will ever see the tilde notation because the interpreting shell expands it before invoking the executable.

Regards,
Alister
# 5  
Old 05-29-2013
Quote:
Originally Posted by elixir_sinari
You've badly messed up the command line and the logic.

Try:
Code:
perl -i.old -ne 'print unless m:^\s*<string>com\.apple\.PhotoBooth</string>\s*$:' ~/Library/Compositions/Compound\ Eye.qtz

I recommend (strongly in your case since you don't seem to understand Perl) taking a copy of the input file (which will be done by the command line automatically with an extension of .old).
I'm already working with duplicate files, so backups are not an issue.

You're absolutely right - I don't understand perl. And many other things, as well. But I learned to do a simple find/replace with it, in this format:
Code:
perl -pi -e 's/read/write/g' /path/to/file

My plan was to use that syntax, except to add the recursive flag and point it at the dir like so:
Code:
perl -pi -e -r 's/^<string>com.apple.PhotoBooth</string>\n$//g' ~/Library/Compositions/

But when I went online to find the newline symbol, I saw that, in their examples, they put the filepath ahead of the command, so I tried it that way, thinking I'd remembered wrong. I also should've used the beginning and end of line markers since I'm grabbing the whole line.
Could you explain what you're doing with your line? Should that colon after the match operator be a slash? I assume that's a match operator, anyway. And why match (m) instead of substitute (s)? Thanks!

---------- Post updated at 05:19 PM ---------- Previous update was at 05:17 PM ----------

Quote:
Originally Posted by xbin
Use PlistBuddy to delete the entry:
Code:
/usr/libexec/PlistBuddy -c "Delete :excludedHosts:0" ~/Library/Compositions/Compound\ Eye.qtz

I started off doing it with BBEdit's find/replace, but there's about twenty files, so I wanted a recursive solution. I don't have PlistBuddy in my installation, although there is another .plist editing app. It seemed easier to edit it as a flat file.

---------- Post updated at 05:20 PM ---------- Previous update was at 05:19 PM ----------

Quote:
Originally Posted by alister
No binaries or scripts invoked by a shell will ever see the tilde notation because the interpreting shell expands it before invoking the executable.

Regards,
Alister
That makes sense.
# 6  
Old 05-29-2013
To be honest, i dislike perl: IMHO it is like a Swiss Army pocket knife: 756 functions - and not one of them in a usable shape.*)

My suggestion is to do it with simple shell commands. UNIX is built with a large toolbox of specialised programs, which - unlike perl - serve only one purpose, but serve this purpose excellently. Use some glue (read: shell scripts) and you can build anything you will ever need and then some.

After this long intro, here is how to do it in shell:

Let us first tackle the removal of a line in a given file. We use "sed" for this and it is really simple:

Code:
sed '/<regexp>/d' /path/to/file > /path/to/output

will remove every line in "/path/to/file", which fits the regexp and output the result to "/path/to/output". Fill in the appropriate regexp (in your case a fixed line) and you are done.

Code:
sed '/<string>com\.apple\.PhotoBooth<\/string>/d' /path/to/file > /path/to/output

Some characters with a special meaning to "sed" got a backslash to let the utility know they are not meant in their special meaning but literal. The rest is straightforward. Test this on a single file and proceed once the results are to your liking.

The next step is to do this for all files recursively. There is a special command for this, which is "find" (i suggest reading its man page, it is by far the most effective "file manager" there is. If you ever have tried to do something with Nautilus, Finder, Norton Commander, etc. - "find" outperforms and outpaces these by some orders of magnitude.)

Let us list all the files you want to change with find:

Code:
find /path/to/some/dir -name "*plist" -print

Again, test and eventually tune it to your needs, proceed once you are satisfied with the results.

Last step: combine the two solutions: we use a simple loop for this:

Code:
find /path/to/dir -name "*plist" -print |\
while read FILE ; do
     sed '/<string>com\.apple\.PhotoBooth<\/string>/d' "$FILE" > "$FILE.tmp"
     mv "$FILE.tmp" "$FILE"
done

Voilą!

OK, there are two details you certainly have detected:

Why did i not use the "-i" flag your "sed" might have (like your perl, which also has it) but used a temp file instead and why did i not use the "-exec" clause, which would have spared me the loop, like this:

Code:
find /path/to/dir -name "*plist" -exec  sed -i '/<string>com\.apple\.PhotoBooth<\/string>/d' {} \;

Answer: the "-i"-flag is problematic, as i have explained here and i try to avoid it. Second, i could have written the two lines necessary to change a single file as a script and called it via "find"s "-exec"-clause, but i saw little gain in this, so i put everything into one script.

I hope this helps.

bakunin
_______
*) try using the screwdriver to actually repair something and you will know what i mean.
This User Gave Thanks to bakunin For This Post:
# 7  
Old 05-29-2013
Quote:
To be honest, I dislike perl
Yes, you have mentioned this to me. ; ) Now, obviously you know more about it than I do, but in my defense let me just say that the little find/replace thing I learned, (or thought I had), appears simple to me:
Code:
perl -pi -e 's/read/write/g' /path/to/file

Much of the reason is that I see "one-liners" as quick and easy. And part of the reason is that it "works in place" rather than creating new files. Also, I like the notion of a perl pie!
But ok, I read your post on the -i flag. I'm not sure how much of that would come into play for me. After all, I'm a truck driver, not a sysadmin, and just playing on my personal computer. But I do understand and appreciate developing good practices, and you are correct to encourage that.
Ok, here are my questions:
How is the line being deleted? Is that what the d operator is saying, delete? And will it then delete any line which contains the preceding string? In other words, if we know that only our target line contains "PhotoBooth", would that be enough to get rid of the whole line?
Code:
'/PhotoBooth/d'

Why do certain characters have to be escaped? I thought if the regex is quoted, it's protected from the shell.
 
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. UNIX for Dummies Questions & Answers

Find & Replace with same case letters

I have text with upper and lower case words. I want to find something and replace it with something new. But it should match the case - Meaning - it should replace old upper cased word with NEW upper case word and lower with lower. example: this text is very simple TEXT. now I want to replace... (5 Replies)
Discussion started by: grep_me
5 Replies

2. UNIX for Dummies Questions & Answers

Find & Replace

Hi I am looking to rename the contents of this dir, each one with a new timestamp, interval of a second for each so it the existing format is on lhs and what I want is to rename each of these to what is on rhs..hopefully it nake sense CDR.20060505.150006.gb CDR.20121211.191500.gb... (3 Replies)
Discussion started by: rob171171
3 Replies

3. UNIX for Dummies Questions & Answers

GREP Find & Replace <p class>

I am making an eBook. I am editing the html in BBedit. I need to replace all <p class="s5"> with just a <p>. How do I write this for GREP? Thank you, Abby (5 Replies)
Discussion started by: cuddlykitty
5 Replies

4. Shell Programming and Scripting

Find & replace --> create a new file

Hi All, I have a unix shell script file as below. My task is a)to replace 248 to 350 and need to create a new file as BW3_350.sh b)to replace 248 to 380 and need to create a new file as BW3_380.sh c)to replace 248 to 320 and need to create a new file as BW3_320.sh there is no... (6 Replies)
Discussion started by: karthi_mrkg
6 Replies

5. Shell Programming and Scripting

Find & Replace string in multiple files & folders using perl

find . -type f -name "*.sql" -print|xargs perl -i -pe 's/pattern/replaced/g' this is simple logic to find and replace in multiple files & folders Hope this helps. Thanks Zaheer (0 Replies)
Discussion started by: Zaheer.mic
0 Replies

6. Shell Programming and Scripting

find & replace with user input

Trying to create a script/executable to replace "abc" text string in "myfile.htm" with input from a pop-up field. For example, launch this thing and a prompt is popped up asking the user to input what "abc" should be replaced with, then it inserts what the user inputs in place of abc in the... (3 Replies)
Discussion started by: mike909
3 Replies

7. UNIX for Dummies Questions & Answers

Find, Replace & Edit a string?

Is this something SED would be used for or can AWK do it? I have a string that I would like to chop bits out of and re-arrange some of the rest. Basically I want to change this: <log4j:event logger="webserver" timestamp="1240110840109" time="Sun Apr 19 04:14:00 BST 2009" level="INFO"... (4 Replies)
Discussion started by: Sepia
4 Replies

8. Shell Programming and Scripting

find & incremental replace?

Looking for a way using sed/awk/perl to replace port numbers in a file with an incrementing number. The original file looks like... Host cmg-iqdrw3p4 LocalForward *:9043 localhost:9043 Host cmg-iqdro3p3a LocalForward *:10000 localhost:10000 Host cmg-iqdro3p3b LocalForward... (2 Replies)
Discussion started by: treadwm
2 Replies

9. UNIX for Dummies Questions & Answers

improving my script (find & replace)

Hi all, I have a script that scan files, find old templet and replace it with new one. #!/bin/ksh file_name=$1 old_templet=$2 new_templet=$3 # Loop through every file like this for file in file_name do cat $file | sed "s/old_templet/new_templet/g" > $file.new #do a global searce and... (8 Replies)
Discussion started by: amir_yosha
8 Replies

10. Shell Programming and Scripting

Find & Replace

I get a text file with 70+ columns (seperated by Tab) and about 10000 rows. The 58th Column is all numbers. But sometimes 58th columns has "/xxx=##" after the numeric data. I want to truncate this string using the script. Any Ideas...:confused: (3 Replies)
Discussion started by: gagansharma
3 Replies
Login or Register to Ask a Question