在一个项目中,我们有如下文本文件:
mv A, R3 mv R2, B mv R1, R3 mv B, R4 add A, R1 add B, R1 add R1, R2 add R3, R3 add R21, X add R12, Y mv X, R2
我需要根据以下内容替换字符串,但我正在寻找更通用的解决方案.
R1 => R2 R2 => R3 R3 => R1 R12 => R21 R21 => R12
我知道我可以在Perl中执行它,以下代码中的replace()函数,但真正的应用程序是用Java编写的,所以解决方案也需要在Java中.
#!/usr/bin/perl use strict; use warnings; use File::Slurp qw(read_file write_file); my %map = ( R1 => 'R2', R2 => 'R3', R3 => 'R1', R12 => 'R21', R21 => 'R12', ); replace(\%map, \@ARGV); sub replace { my ($map, $files) = @_; # Create R12|R21|R1|R2|R3 # making sure R12 is before R1 my $regex = join "|", sort { length($b) <=> length($a) } keys %$map; my $ts = time; foreach my $file (@$files) { my $data = read_file($file); $data =~ s/\b($regex)\b/$map{$1}/g; rename $file, "$file.$ts"; # backup with current timestamp write_file( $file, $data); } }
您对Java实现的帮助将不胜感激.
在过去的两周里,我实际上不得不多次使用这种算法.所以这是世界上第二个最冗长的语言......
import java.util.HashMap; import java.util.regex.Pattern; import java.util.regex.Matcher; /* R1 => R2 R2 => R3 R3 => R1 R12 => R21 R21 => R12 */ String inputString = "mv A, R3\n" + "mv R2, B\n" + "mv R1, R3\n" + "mv B, R4\n" + "add A, R1\n" + "add B, R1\n" + "add R1, R2\n" + "add R3, R3\n" + "add R21, X\n" + "add R12, Y\n" + "mv X, R2" ; System.out.println( "inputString = \"" + inputString + "\"" ); HashMap h = new HashMap(); h.put( "R1", "R2" ); h.put( "R2", "R3" ); h.put( "R3", "R1" ); h.put( "R12", "R21" ); h.put( "R21", "R12" ); Pattern p = Pattern.compile( "\\b(R(?:12?|21?|3))\\b"); Matcher m = p.matcher( inputString ); StringBuffer sbuff = new StringBuffer(); int lastEnd = 0; while ( m.find()) { int mstart = m.start(); if ( lastEnd < mstart ) { sbuff.append( inputString.substring( lastEnd, mstart )); } String key = m.group( 1 ); String value = (String)h.get( key ); sbuff.append( value ); lastEnd = m.end(); } if ( lastEnd < inputString.length() ) { sbuff.append( inputString.substring( lastEnd )); } System.out.println( "sbuff = \"" + sbuff + "\"" );
这可以是Java-ified这些类:
import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; interface StringReplacer { public CharSequence getReplacement( Matcher matcher ); } class Replacementifier { static Comparator keyComparator = new Comparator() { public int compare( Object o1, Object o2 ) { String s1 = (String)o1; String s2 = (String)o2; int diff = s1.length() - s2.length(); return diff != 0 ? diff : s1.compareTo( s2 ); } }; Map replaceMap = null; public Replacementifier( Map aMap ) { if ( aMap != null ) { setReplacements( aMap ); } } public setReplacements( Map aMap ) { replaceMap = aMap; } private static String createKeyExpression( Map m ) { Set set = new TreeSet( keyComparator ); set.addAll( m.keySet()); Iterator sit = set.iterator(); StringBuffer sb = new StringBuffer( "(" + sit.next()); while ( sit.hasNext()) { sb.append( "|" ).append( sit.next()); } sb.append( ")" ); return sb.toString(); } public String replace( Pattern pattern, CharSequence input, StringReplacer replaceFilter ) { StringBuffer output = new StringBuffer(); Matcher matcher = pattern.matcher( inputString ); int lastEnd = 0; while ( matcher.find()) { int mstart = matcher.start(); if ( lastEnd < mstart ) { output.append( inputString.substring( lastEnd, mstart )); } CharSequence cs = replaceFilter.getReplacement( matcher ); if ( cs != null ) { output.append( cs ); } lastEnd = matcher.end(); } if ( lastEnd < inputString.length() ) { sbuff.append( inputString.substring( lastEnd )); } } public String replace( Map rMap, CharSequence input ) { // pre-condition if ( rMap == null && replaceMap == null ) return input; Map repMap = rMap != null ? rMap : replaceMap; Pattern pattern = Pattern.compile( createKeyExpression( repMap )) ; StringReplacer replacer = new StringReplacer() { public CharSequence getReplacement( Matcher matcher ) { String key = matcher.group( 1 ); return (String)repMap.get( key ); } }; return replace( pattern, input, replacer ); } }