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?
If you open Terminal,
cdinto the directory that contains these files, I find this to be the best to find those files:This finds everything within the current
.directory that is a file-type fthat has a name of*.m,*.mm,*.mmmmm, and so on (the*.m*). You then output each resulting file-printto the console (or a pipe). If you wish to pass each of the files to another process (usingxargs), it is best to replace-printwith-print0so it correctly handles whitespace in the filenames.Next, use
sedto replace the text within those results. (The version ofsedthat comes with Mac is different from the GNUsed, 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:
The
-i ""replaces the file in-place (saves it to the same file that was opened).-ejust means the next text is going to be an expression. Starting the expression withs/signifies that you are going to be doing a search-and-replace. It is usually in the format:The
/gat 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 sosedknows to remember it).The replacement pattern,
/NSLocalizedStringFromTable(\1, table, \2)/, replaced theNSLocalizedStringwithNSLocalizedStringFromTable, and then tucked the exact replacement of the first and second\(.*\)pairs into the\1and\2references.If you had this literal value:
then the result would become:
Now, @shellter asked in the comments whether you meant that you want the literal word
tableto 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:
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.