sed replace multiple patterns with certain string

I've been tasked with replacing a whole lot of hardcoded ID's in some code (for example: private static String MERCHANT_ID = "1234";) with references to a config file somewhere (so the replaced version for this example should be private static String MERCHANT_ID = ConstantMerchants.MERCHANT_A;).

The default find and replace function in Eclipse would be fine if I were replacing just a few ID's, but I'm not. I have twenty projects, all of them contain hundreds of files with multiple different notations of the old string.

I've already compiled a list of regex patterns that match every possible notation.

Is there a way to use sed to replace all old strings with the new versions by having a configuration file somewhere containing the old pattern, and what it should be replaced with?

I'm looking for something that allows me to define patterns with a new value, think of something similar to this: (but then with quite a few more ID's)

# old | new
/merchantId:\s*("|')1234("|'),/|merchantId: ConstantMerchants.MERCHANT_A
/private static String MERCHANT_ID\s*=\s*("|')1234("|');/|private static String MERCHANT_ID = ConstantMerchants.MERCHANT_A

If I should use some other tool that'll help me better resolve this issue, I'd love to hear about it. I'd very much like to use the new Bash on Windows feature, but that is only because it looks cool :)

4

2 Answers

As I understand it the problem is that you have a set of syntax patterns to match, and independently a lot of possible numbers that need to be translated, and you need to "multiply" these together. The following might be a suitable sed mechanism, assuming some simplification: in your sed first use the patterns to match lines, then use the number conversion on these lines. Eg create a file sedscript holding

/merchantId:\s*("|')[0-9]+("|')/b change
/private static String MERCHANT_ID\s*=\s*("|')[0-9]+("|')/b change
b
:change
s/["']1234["']/ConstantMerchants.MERCHANT_A/
s/["']1235["']/ConstantMerchants.MERCHANT_B/

It starts with each of your patterns followed by the command b change which means branch to the label change when the pattern is found. The list of patterns ends with the command b which means branch to the end, i.e. move on to read the next input line from the file.

The :change means this is the label change where we branch to. Then follows each of your possible number to name translations. The simplification is to assume that only one number in quotes will appear on the line, so we can ignore which actual pattern matched. If there are some exceptions to this, it might be worth handling those by hand.

On a Unix system (I don't know about windows) you could use this shell script to edit the files:

find dir -type f |
xargs sed -i -r -f sedscript

The -i will edit the files in-place, so always start by copying the files to a new directory dir, then run this command on the copy, and use diff -ru between the two directories to verify that it is doing what you want. The -r is needed (on Unix) to have GNU sed accept (a|b) instead of the usual \(a\|b\) pattern.

1

By looking at the MAN Page you'll see that sed supports a -f parameter to supply a script file. Said file should contain every replace to run as you'd supply it to sed directly. So e.g. you'd have:

  • s/old/new/
  • s/new/old/

On separate lines in the file and it would apply both commands to whatever you supply by stdout. As an example: echo "old" | sed -f script.file with the above content would lead to the output old.

To apply said rules to multiple files, one option would be to use a loop in which you run sed with the script for each file and save the changes to the file itself. Another would be to use the option -i and supply "all" files as command line arguments. Depending on the number you might run into issues with the total length of the command.

2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like