0

Last week I accidently externalized all my strings of my eclipse project. I need to revert this and my only hope is sed. I tried to create scripts but failed pathetically because I'm new with sed and this would be a very complicated operation. What I need to do is this:

Strings in class.java file is currently in the following format(method) Messages.getString(<key>). Example :

    if (new File(DataSource.DEFAULT_VS_PATH).exists()) {
        for (int i = 1; i <= c; i++) {
            if (!new File(DataSource.DEFAULT_VS_PATH
                    + Messages.getString("VSDataSource.89") + i).exists()) { //$NON-NLS-1$
                getnewvfspath = DataSource.DEFAULT_VS_PATH
                        + Messages.getString("VSDataSource.90") + i; //$NON-NLS-1$
                break;
            }
        }
    }

The key and matching Strings are in messages.properties file in the following format.

VSDataSource.92=No of rows in db = 
VSDataSource.93=Verifying db entry : 
VSDataSource.94=DB is open
VSDataSource.95=DB is closed
VSDataSource.96=Invalid db entry for 
VSDataSource.97=\ removed.
key=string

So I need the java file back in this format:

    if (new File(DataSource.DEFAULT_VS_PATH).exists()) {
        for (int i = 1; i <= c; i++) {
            if (!new File(DataSource.DEFAULT_VS_PATH
                    + "String 2" + i).exists()) { //$NON-NLS-1$
                getnewvfspath = DataSource.DEFAULT_VS_PATH
                        + "String 1" + i; //$NON-NLS-1$
                break;
            }
        }
    }

How can I accomplish this with sed? Or is there an easier way?

Binoy Babu
  • 16,699
  • 17
  • 91
  • 134
  • 1
    So I'm guessing `VSDataSource.89` is `String 2` in your `messages.properties`? Are you wanting to replace `Messages.getString('VSDataSource.xxx')` with the `yyy` from `VSDataSource.xxx=yyy` in `messages.properties`? – mathematical.coffee Apr 03 '12 at 23:29
  • @mathematical.coffee yes. The `key` needn't start with `VSDataSource`, but it is unique for each string. – Binoy Babu Apr 03 '12 at 23:31
  • Use Java? Here's a similar thing: http://stackoverflow.com/questions/4766602/un-externalize-strings-from-eclipse-or-intellij. Instead of making the strings in the Java file, you can go through all the files and do a regex search and replace. – icyrock.com Apr 03 '12 at 23:35
  • @icyrock.com I'm aware of that question, but my question is a bit different. Also note that the op was not that satisfied with that answer. I did a regex search but still i have to manually type in more than 200 strings top the replace box. – Binoy Babu Apr 03 '12 at 23:39
  • 1
    Make a Java program in which you can: 1) read the properties, 2) traverse all your project .java files, 4) read each file line by line, replace all the strings by using regexps, keying from the loaded properties, save when done reading all lines. Not a 2-minute job, but easy enough. – icyrock.com Apr 03 '12 at 23:44

4 Answers4

4

This might work for you (GNU sed?):

sed 's|^\([^=]*\)=\(.*\)|s@Messages.getString("\1")@"\2"@g|;s/\\/\\\\/g' messages.properties |
sed -i -f - *.java
potong
  • 55,640
  • 6
  • 51
  • 83
  • Nice. I would suggest -i.bak or something, just for double-checking later. – Miserable Variable Apr 04 '12 at 00:40
  • `OSListActivity.100=/system/bootmenu/recovery/sbin/tune2fs -j ` There are many entries like this in messages.properties. So sed: file - line 52: unknown option to `s' – Binoy Babu Apr 04 '12 at 00:45
  • Just change the `s/../../g` to some `s@..@..@g` see solution: You can also run the first part and check the sed generated script by hand, when happy save it as `temp.sed` and run `sed -f temp.sed *.java` – potong Apr 04 '12 at 00:49
  • It worked, other answers are great too, but this one's special because it's a oneliner. I love stackoverfow. – Binoy Babu Apr 04 '12 at 01:14
  • Without seeing the data I can't tell you why or how to amend the solution. However, since this is a *one-off* you might just have to dive into an editor and fix up those exceptions by hand, Good luck! – potong Apr 05 '12 at 05:26
2

To repeat my comment on the question - I think that Java problems are best solved in Java :) Though this arguably is an Eclipse-helped problem caused by you :)

Make a Java program in which you can:

  • Read the properties,
  • Traverse all your project .java files,
  • For each file:
    • Read each file line by line,
    • Replace all the strings by using regexps, keying from the loaded properties,
    • Save when done reading all lines.

Not a 2-minute job, but easy enough.

But if you really want to use sed ;)

mkt.sh

$ cat mkt.sh
# Test structure
rm -rf a b
mkdir a
mkdir b
cat > a/A.java <<EOF
my plans for replace
this will be left alone 
EOF
cat > b/B.java <<EOF
propery ginger
broccoli tomato potato
EOF

display() {
  for i in a/A.java b/B.java; do
    echo --- $i
    cat $i
  done
}

display

# Prop change
echo 'echo --- Replacing in: $1' > replace.sh
sed -r 's/([^=]+)=(.+)/sed -i '\''s#\1#\2#'\'' $1/' sample.properties >> replace.sh
chmod u+x replace.sh

# Replace
find -type f -name "*.java"|xargs -n1 ./replace.sh

# Test
display

Run:

$ ./mkt.sh 
--- a/A.java
my plans for replace
this will be left alone 
--- b/B.java
propery ginger
broccoli tomato potato
--- Replacing in: ./a/A.java
--- Replacing in: ./b/B.java
--- a/A.java
my plans for world domination
this will be left alone 
--- b/B.java
propery ginger
steak tomato potato

This should work properly on your .java files, but do make a copy before ;) You will have some issues if # is in the strings, but you can solve this by removing these from properties file, doing a replace, bringing them back and changing this line:

sed -r 's/([^=]+)=(.+)/sed -i '\''s#\1#\2#'\'' $1/' sample.properties >> replace.sh

to e.g.:

sed -r 's/([^=]+)=(.+)/sed -i '\''s+\1+\2+'\'' $1/' sample.properties >> replace.sh

where + is not a remaining character. A bit of a hassle, but...

Hope this helps.

icyrock.com
  • 27,952
  • 4
  • 66
  • 85
  • Can you give me a few (random lines of the ones that had error) from the generated `replace.sh` (and / or your properties file if possible)? – icyrock.com Apr 04 '12 at 00:38
  • Besides - which OS, bash version, sed version? That can be very important, as some of them don't support options (such as `-r` given to `sed` or things like that) – icyrock.com Apr 04 '12 at 00:45
  • ubuntu 12.04, GNU bash, version 4.2.20(1)-release (i686-pc-linux-gnu), GNU sed version 4.2.1 – Binoy Babu Apr 04 '12 at 00:50
  • Ubuntu, nice :) OK, this is good - I have Ubuntu 11.10, so should be good. Can you give me some of the rows that failed? Like this one: `./replace.sh: 350: ./replace.sh: VSDataSource.40=: not found` and around (seems these in `VSDataSource` fail often). – icyrock.com Apr 04 '12 at 00:54
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/9659/discussion-between-icyrock-com-and-binoy-babu) – icyrock.com Apr 04 '12 at 01:01
2

makesed.awk:

BEGIN {
    FS="=";
    print "for i in *.java"
    print "do"
    print "sed \\"
}

{
    msg = "Messages.getString(\"" $1 "\")";
    gsub("/","\\/",$2);
    print "-e 's/" msg "/\"" $2 "\"/g' \\"
}

END {
    print "$i > $$"
    print "mv $$ $i"
    print "done" 
}

Run:

awk -f makesed.awk yourpropertiesfile.dat > process.sh

This gives you a shell script:

for i in *.java
do
sed \
-e 's/Messages.getString("VSDataSource.92")/"No of rows in db "/g' \
-e 's/Messages.getString("VSDataSource.93")/"Verifying db entry : "/g' \
-e 's/Messages.getString("VSDataSource.94")/"DB is open"/g' \
-e 's/Messages.getString("VSDataSource.95")/"DB is closed"/g' \
-e 's/Messages.getString("VSDataSource.96")/"Invalid db entry for "/g' \
-e 's/Messages.getString("VSDataSource.97")/"\ removed."/g' \
$i > $$
mv $$ $i
done

Then go in to your respective Java directories and run:

sh process.sh

That will "fix" all of the java files in that directory.

If your properties file is long, you may very well run in to a command line limit with sed. Simply split the file up in to chunks until the script is happy.

Obviously this doesn't work with any escape character, if you have "=" in your messages you'll suffer some pain as well. If you're fool enough to run this on code that isn't backed up, then you certainly deserve whatever happens to you.

But it should be a good first start.

Will Hartung
  • 115,893
  • 19
  • 128
  • 203
-1

You don't need to program anything. Right-click on one of your modified files and select "Replace With >", "Previous from Local History". Repeat as necessary.

phatfingers
  • 9,770
  • 3
  • 30
  • 44
  • Please read the first line of the question. I have modified the code many times after externalization. It's almost impossible to replace with history. – Binoy Babu Apr 03 '12 at 23:40
  • That would be the line that says last week you accidentally externalized your strings in your eclipse project? It's only Tuesday, you know... – phatfingers Apr 03 '12 at 23:45
  • :D thats funny, I did it last monday. – Binoy Babu Apr 03 '12 at 23:46
  • If you chose `Replace With` and `Local History`, it lists a set of dates for each change. Should be easy enough to find the date/time on Monday on which the change occurred, then revert each file based on that date. But of course we don't know if you've been heavily developing your code over the last week. – phatfingers Apr 03 '12 at 23:53
  • I've been heavily developing, as I said replacing with local history is not an option. – Binoy Babu Apr 03 '12 at 23:57