代码之家  ›  专栏  ›  技术社区  ›  szabgab Brandon Fosdick

如何用Java替换文本中的字符串?

  •  5
  • szabgab Brandon Fosdick  · 技术社区  · 17 年前

    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);
        }
    }
    

    5 回复  |  直到 17 年前
        1
  •  5
  •   Axeman maxelost    17 年前

    事实上,在过去的两周里,我已经多次使用这种算法。所以这里它是世界上第二个最冗长的语言。。。

    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 + "\"" );
    

    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 ); 
        }
    }
    
        2
  •  2
  •   user3458 user3458    17 年前

    perl解决方案的优点是一次替换所有字符串,有点“事务性”。如果在Java中没有相同的选项(我想不出一种方法来实现),那么需要小心替换R1=>R2,然后R2=>R3。在这种情况下,R1和R2最终都被R3取代。

        3
  •  0
  •   Alan Moore Chris Ballance    17 年前

    下面是一种使用Matcher的低级API一次性完成此操作的不太详细的方法: appendReplacement() appendTail()

    import java.util.*;
    import java.util.regex.*;
    
    public class Test
    {
      public static void main(String[] args) throws Exception
      {
        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);
          System.out.println();
          System.out.println(doReplace(inputString));
      }
    
      public static String doReplace(String str)
      {
         Map<String, String> map = new HashMap<String, String>()
         {{
            put("R1", "R2");
            put("R2", "R3");
            put("R3", "R1");
            put("R12", "R21");
            put("R21", "R12");
         }};
    
         Pattern p = Pattern.compile("\\bR\\d\\d?\\b");
         Matcher m = p.matcher(str);
         StringBuffer sb = new StringBuffer();
         while (m.find())
         {
           String repl = map.get(m.group());
           if (repl != null) 
           {
             m.appendReplacement(sb, "");
             sb.append(repl);
           }
         }
         m.appendTail(sb);
         return sb.toString();
      }
    }
    

    附录替换() 处理要替换的替换字符串 $n append() 方法。

    Elliott Hughes已经发布了该技术的预打包实现 here main() 方法,然后再编译它。)

        4
  •  0
  •   FatherMathew    11 年前

    我的建议是在读取文件本身时替换字符串 你可以用 . 在逐字读取文件时, 实际上,您可以检查该模式,然后自己进行替换。然后您可以将所有内容一次写入该文件。我想这会节省你更多的时间。

        5
  •  -2
  •   kgiannakakis    17 年前

    Map<String, String> map = new HashMap<String, String>();
    map.put("R1", "R2");
    map.put("R2", "R3");
    
    for(String key: map.keySet()) {
      str.replaceAll(key, map.get(key));
    }
    

    replaceAll还处理正则表达式。

    编辑:正如许多人指出的那样,上述解决方案不起作用,因为它不处理循环替换。这是我的第二种方法:

    public class Replacement {
    
        private String newS;
        private String old;
    
        public Replacement(String old, String newS) {
            this.newS = newS;
            this.old = old;
        }
    
        public String getOld() {
            return old;
        }
    
        public String getNew() {
            return newS;
        }
    }
    
    SortedMap<Integer, Replacement> map = new TreeMap<Integer, Replacement>();
    
    map.put(new Integer(1), new Replacement("R2", "R3"));
    map.put(new Integer(2), new Replacement("R1", "R2"));
    
    for(Integer key: map.keySet()) {
       str.replaceAll(map.get(key).getOld(), map.get(key).getNew());
    }
    

    R1 -> R2
    R2 -> R3
    R3 -> R1
    

    您必须为以下各项使用一些“临时”变量:

    R1 -> R@1
    R2 -> R@3
    R3 -> R1
    R@(\d{1}) -> R\1
    

    你可以写一个库,它可以为你做所有这些。