1

I want to do string manipulation in multiple files in a directory hierarchy.

I basically have a project directory with .m files and I want to look into all the files; find all instances of NSLocalizedString(key, comment) and change that to NSLocalizedStringFromTable (key, table, comment).

Simple Find & Replace cannot work because I need to insert the 'table' in between and I cannot do this manually as there are at least 1200 instances of this through the project.

The logic would be something like this I guess:

  • loop through the directory structure to find all .m files

  • find all instances of "NSLocalizedString"

  • copy the "key" and "comment" in variables var1 & var 2

  • replace NSLocalizedString(key, comment) with NSLocalizedStringFromTable(var1, table, var2)

  • save the file (not replace it, save it)

So how do I write the script to do this?

5
  • 2
    What's your specific programming question? Commented Nov 15, 2011 at 16:26
  • I have edited with my question in the end Commented Nov 15, 2011 at 16:38
  • 2
    That's not a specific programming question. It's asking us to write the script for you. StackOverflow is about solving specific problems, not having people write your code. Commented Nov 15, 2011 at 16:41
  • A combination of grep, sed and find will solve this problem. Hint: It is a "simple search and replace" problem. Commented Nov 15, 2011 at 16:44
  • you wrote 'replace NSLocalizedString(key, comment) with NSLocalizedStringFromTable(var1, table, var2)'. Do you mean just replace the strings (almost) as shown OR do you mean to lookup 'key' in an external table and substitute a new value into your text based on the key-value found in the table (plus the new functionName of course). Good luck. Commented Nov 15, 2011 at 17:50

3 Answers 3

1

If you open Terminal, cd into the directory that contains these files, I find this to be the best to find those files:

find . -type f -name "*.m*" -print
This finds everything within the current . directory that is a file -type f that has a name of *.m, *.mm, *.mmmmm, and so on (the *.m*). You then output each resulting file -print to the console (or a pipe). If you wish to pass each of the files to another process (using xargs), it is best to replace -print with -print0 so it correctly handles whitespace in the filenames.

Next, use sed to replace the text within those results. (The version of sed that comes with Mac is different from the GNU sed, and will not properly handle newlines and other special characters correctly. You may need to grab that version if this does not work for you.)

The basic structure of the replacement is:

sed -i "" -e 's/NSLocalizedString(\(.*\), \(.*\))/NSLocalizedStringFromTable(\1, table, \2)/g' "FILENAME"
The -i "" replaces the file in-place (saves it to the same file that was opened). -e just means the next text is going to be an expression. Starting the expression with s/ signifies that you are going to be doing a search-and-replace. It is usually in the format:
s/[search for this pattern]/[replace with this pattern]/g
The /g at the end means 'global', or "do this for as many instances that are found on each line as possible."

The search pattern, /NSLocalizedString(\(.*\), \(.*\))/, finds that text and then copies the contents of the \(...\) tags (you have to escape the parentheses so sed knows to remember it).

The replacement pattern, /NSLocalizedStringFromTable(\1, table, \2)/, replaced the NSLocalizedString with NSLocalizedStringFromTable, and then tucked the exact replacement of the first and second \(.*\) pairs into the \1 and \2 references.

If you had this literal value:

NSLocalizedString(@"Darn tootin'", @"How they say 'that is correct' in some dialects");
then the result would become:
NSLocalizedStringFromTable(@"Darn tootin'", table, @"How they say 'that is correct' in some dialects");

Now, @shellter asked in the comments whether you meant that you want the literal word table to be in there, whether parameter 1 or parameter 2 should come from different tables, etc. That would certainly change the format of this search string.

Lastly, you can combine the two above features into one long shell script and run it in Terminal:

find . -type f -name "*.m*" -print0| \
xargs -0 -I FILENAME \
sed -i "" -e 's/NSLocalizedString(\(.*\), \(.*\))/NSLocalizedStringFromTable(\1, table, \2)/g' "FILENAME"

If you meant for different values to be in place of "var1" and "var2" that you mentioned in your original post, you'll need to specify.

Sign up to request clarification or add additional context in comments.

Comments

1

Since this is a Cocoa project, why can't you just use the project-wide find and replace (⌘⌥⇧F) in the IDE? This is what it's for.

1 Comment

I have 1200 instances of NSLocalizedString(key, comment) to replace with NSLocalizedStringFromTable(key, table, comment) and key and comment should not change and insert "table" value in between. I don't think XCode allows to do that complex replace
0

You need to post a few samples to get an idea the pattern to replace but this seems like a simple enough problem. Realize that you can use ["^]*? to stop at the ". From there it's just breaking it up appropriately and putting it back together.

An example would be

'(NSLocalizedString\()("["^]*?)(,)("["^]*?)(\))', '\1\2\3#TABLE#\3\4\5'

This example takes NSLocalizedString("var1", "var2") as input and makes it NSLocalizedString("var1", #table#, "var2").

2 Comments

I will try this out. I am sorry couldn't provide any example as I am absolutely new to Shell Script so didn't want to confuse the reader by posting a wrong example.
Well ideally with regex you want to know what you have and from there you can do anything.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.