76

如何在 Java 中修剪字符?
例如

String j = “\joe\jill\”.Trim(new char[] {“\”});

j应该是

“乔\吉尔”

String j = “jack\joe\jill\”.Trim("jack");

j应该是

“\乔\吉尔\”

ETC

4

14 回答 14

110

Apache Commons有一个很棒的StringUtils 类(org.apache.commons.lang.StringUtils)。有StringUtils一种strip(String, String)方法可以做你想做的事。

无论如何,我强烈推荐使用 Apache Commons,尤其是 Collections 和 Lang 库。

于 2010-01-18T20:16:56.820 回答
46

这可以满足您的要求:

public static void main (String[] args) {
    String a = "\\joe\\jill\\";
    String b = a.replaceAll("\\\\$", "").replaceAll("^\\\\", "");
    System.out.println(b);
}

$用于删除字符串末尾的序列。用于在^开始时删除。

作为替代方案,您可以使用以下语法:

String b = a.replaceAll("\\\\$|^\\\\", "");

意思是“|或”。

如果您想修剪其他字符,只需调整正则表达式:

String b = a.replaceAll("y$|^x", ""); // will remove all the y from the end and x from the beggining
于 2010-01-18T18:11:31.580 回答
20

CharMatcher– 谷歌番石榴

过去,我会选择 Colins 的 Apache commons-lang answer。但是现在 Google 的guava-libraries已经发布,CharMatcher类会很好地满足你的需求:

String j = CharMatcher.is('\\').trimFrom("\\joe\\jill\\"); 
// j is now joe\jill

CharMatcher有一组非常简单和强大的 API 以及一些预定义的常量,使操作变得非常容易。例如:

CharMatcher.is(':').countIn("a:b:c"); // returns 2
CharMatcher.isNot(':').countIn("a:b:c"); // returns 3
CharMatcher.inRange('a', 'b').countIn("a:b:c"); // returns 2
CharMatcher.DIGIT.retainFrom("a12b34"); // returns "1234"
CharMatcher.ASCII.negate().removeFrom("a®¶b"); // returns "ab";

非常好的东西。

于 2010-01-19T03:31:00.157 回答
8

这是另一个非正则表达式,非超级棒,非超级优化,但非常容易理解的非外部库解决方案:

public static String trimStringByString(String text, String trimBy) {
    int beginIndex = 0;
    int endIndex = text.length();

    while (text.substring(beginIndex, endIndex).startsWith(trimBy)) {
        beginIndex += trimBy.length();
    } 

    while (text.substring(beginIndex, endIndex).endsWith(trimBy)) {
        endIndex -= trimBy.length();
    }

    return text.substring(beginIndex, endIndex);
}

用法:

String trimmedString = trimStringByString(stringToTrim, "/");
于 2012-02-13T15:00:47.137 回答
1

您可以使用removeStartremoveEnd来自 Apache Commons Lang StringUtils

于 2010-01-18T18:15:09.667 回答
1

为第一个选项手工制作:

public class Rep {
    public static void main( String [] args ) {
       System.out.println( trimChar( '\\' , "\\\\\\joe\\jill\\\\\\\\" )  ) ;
       System.out.println( trimChar( '\\' , "joe\\jill" )  ) ;
    }
    private static String trimChar( char toTrim, String inString ) { 
        int from = 0;
        int to = inString.length();

        for( int i = 0 ; i < inString.length() ; i++ ) {
            if( inString.charAt( i ) != toTrim) {
                from = i;
                break;
            }
        }
        for( int i = inString.length()-1 ; i >= 0 ; i-- ){ 
            if( inString.charAt( i ) != toTrim ){
                to = i;
                break;
            }
        }
        return inString.substring( from , to );
    }
}

印刷

joe\jil

joe\jil

于 2010-01-18T18:51:53.843 回答
1
public static String trim(String value, char c) {

    if (c <= 32) return value.trim();

    int len = value.length();
    int st = 0;
    char[] val = value.toCharArray();    /* avoid getfield opcode */

    while ((st < len) && (val[st] == c)) {
        st++;
    }
    while ((st < len) && (val[len - 1] == c)) {
        len--;
    }
    return ((st > 0) || (len < value.length())) ? value.substring(st, len) : value;
}
于 2017-01-20T23:13:48.080 回答
0

编辑:由答案修改以仅替换第一个和最后一个 '\' 字符。

System.err.println("\\joe\\jill\\".replaceAll("^\\\\|\\\\$", ""));
于 2010-01-18T17:52:51.907 回答
0

我认为没有任何内置函数可以根据传入的字符串进行修剪。这是一个如何做到这一点的小例子。这可能不是最有效的解决方案,但对于大多数情况,它可能足够快,评估并适应您的需求。我建议对将定期使用的任何代码片段进行性能测试并根据需要进行优化。下面,我以一些时间信息为例。

public String trim( String stringToTrim, String stringToRemove )
{
    String answer = stringToTrim;

    while( answer.startsWith( stringToRemove ) )
    {
        answer = answer.substring( stringToRemove.length() );
    }

    while( answer.endsWith( stringToRemove ) )
    {
        answer = answer.substring( 0, answer.length() - stringToRemove.length() );
    }

    return answer;
}

此答案假定要修剪的字符是字符串。例如,传入“abc”将删除“abc”,但不会删除“bbc”或“cba”等。

运行以下 1000 万次中的每一个的一些性能时间。

" mile ".trim();运行时间为 248 毫秒,作为性能比较的参考实现。

trim( "smiles", "s" );运行时间为 547 毫秒 - 大约是 javaString.trim()方法的 2 倍。

"smiles".replaceAll("s$|^s","");运行时间为 12,306 毫秒 - 大约是 javaString.trim()方法的 48 倍。

并且使用编译的正则表达式模式Pattern pattern = Pattern.compile("s$|^s"); pattern.matcher("smiles").replaceAll("");在 7,804 毫秒内运行 - 大约是 javaString.trim()方法的 31 倍。

于 2010-01-18T17:59:41.077 回答
0

似乎没有现成的使用 java api 可以做到这一点,但您可以编写一个方法来为您做到这一点。这个链接可能有用

于 2010-01-18T18:01:19.113 回答
0

实际上,我会编写自己的小函数,通过使用普通的旧字符访问来解决问题:

public static String trimBackslash( String str )
{
    int len, left, right;
    return str == null || ( len = str.length() ) == 0 
                           || ( ( left = str.charAt( 0 ) == '\\' ? 1 : 0 ) |
           ( right = len > left && str.charAt( len - 1 ) == '\\' ? 1 : 0 ) ) == 0
        ? str : str.substring( left, len - right );
}

这与 String.trim() 的行为类似,只是它使用 '\' 而不是空格。

这是一种可行且实际使用 trim() 的替代方法。;) 尽管它的效率不是很高,但它可能会在性能方面击败所有基于正则表达式的方法。

String j = “\joe\jill\”;
j = j.replace( '\\', '\f' ).trim().replace( '\f', '\\' );
于 2010-01-18T19:07:20.207 回答
0

这就是我将如何做到的。

我认为它的效率是合理的。它优化了单个字符的大小写,并避免为每个删除的子序列创建多个子字符串。

请注意,处理将空字符串传递给修剪的极端情况(其他一些答案将进入无限循环)。

/** Trim all occurrences of the string <code>rmvval</code> from the left and right of <code>src</code>.  Note that <code>rmvval</code> constitutes an entire string which must match using <code>String.startsWith</code> and <code>String.endsWith</code>. */
static public String trim(String src, String rmvval) {
    return trim(src,rmvval,rmvval,true);
    }

/** Trim all occurrences of the string <code>lftval</code> from the left and <code>rgtval</code> from the right of <code>src</code>.  Note that the values to remove constitute strings which must match using <code>String.startsWith</code> and <code>String.endsWith</code>. */
static public String trim(String src, String lftval, String rgtval, boolean igncas) {
    int                                 str=0,end=src.length();

    if(lftval.length()==1) {                                                    // optimize for common use - trimming a single character from left
        char chr=lftval.charAt(0);
        while(str<end && src.charAt(str)==chr) { str++; }
        }
    else if(lftval.length()>1) {                                                // handle repeated removal of a specific character sequence from left
        int vallen=lftval.length(),newstr;
        while((newstr=(str+vallen))<=end && src.regionMatches(igncas,str,lftval,0,vallen)) { str=newstr; }
        }

    if(rgtval.length()==1) {                                                    // optimize for common use - trimming a single character from right
        char chr=rgtval.charAt(0);
        while(str<end && src.charAt(end-1)==chr) { end--; }
        }
    else if(rgtval.length()>1) {                                                // handle repeated removal of a specific character sequence from right
        int vallen=rgtval.length(),newend;
        while(str<=(newend=(end-vallen)) && src.regionMatches(igncas,newend,rgtval,0,vallen)) { end=newend; }
        }

    if(str!=0 || end!=src.length()) {
        if(str<end) { src=src.substring(str,end); }                            // str is inclusive, end is exclusive
        else        { src="";                     }
        }

    return src;
    }
于 2010-01-19T21:20:03.803 回答
0

10 岁的问题,但觉得大多数答案有点令人费解或不太像被问到的那样工作。此外,这里最受好评的答案也没有提供任何示例。这是我制作的一个简单的类:

https://gist.github.com/Maxdw/d71afd11db2df4f1297ad3722d6392ec

用法

Trim.left("\joe\jill\", "\") == "joe\jill\"

Trim.left("jack\joe\jill\", "jack") == "\joe\jill\"

Trim.left("\\\\joe\\jill\\\\", "\") == "joe\\jill\\\\"
于 2019-05-09T13:59:35.307 回答
0

我的解决方案:

private static String trim(String string, String charSequence) {
        var str = string;
        str = str.replace(" ", "$SAVE_SPACE$").
                  replace(charSequence, " ").
                  trim().
                  replace(" ", charSequence).
                  replace("$SAVE_SPACE$", " ");
        return str;
    }
于 2020-10-15T21:34:22.167 回答