Обрезать символы в Java

Как я могу обрезать символы в Java?
например.

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

j должно быть

"Джо \ Джилл"

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

j должно быть

"\Джо\Джилл\"

так далее


person Quintin Par    schedule 18.01.2010    source источник
comment
Что должен \\\\joe\\jill\\\\` should return? joe\\jill` ??   -  person OscarRyz    schedule 18.01.2010
comment
@Оскар, да. Нравится отделка в .net   -  person Quintin Par    schedule 18.01.2010
comment
Я не думаю, что эта операция называется обрезкой...   -  person Esko    schedule 18.01.2010
comment
Но я просто ищу trim char, чтобы найти этот вопрос, ура.   -  person aristotll    schedule 15.01.2018


Ответы (13)


Apache Commons имеет отличный класс StringUtils (org.apache.commons.lang.StringUtils). В StringUtils есть метод strip(String, String), который будет делать то, что вы хотите.

В любом случае я настоятельно рекомендую использовать Apache Commons, особенно библиотеки Collections и Lang.

person Colin Gislason    schedule 18.01.2010
comment
Действительно хорошее решение. - person user218867; 27.08.2015

Это делает то, что вы хотите:

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
person Paulo Guedes    schedule 18.01.2010
comment
Я думаю, вам нужно добавить \\ , т.е. "\\y$|^\\x" - person EricG; 22.02.2017
comment
ты не имеешь в виду "\\\\+$"? - person SparK; 11.07.2019

CharMatcher – Google Гуава

Раньше я был вторым ответом Colins на Apache commons-lang. Но теперь, когда выпущены библиотеки гуавы, 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";

Очень хороший материал.

person Cowan    schedule 19.01.2010
comment
???? Проверьте CharMatcher в Google Гуаве. Гладкая штука. Умное использование синтаксиса Predicate. Позволяет легко указать, какое из различных определений пробельных, невидимых и управляющих символов вы имеете в виду. В документе есть ссылка на интересную электронную таблицу, в которой перечислены некоторые различные определения пробелов. - person Basil Bourque; 29.11.2014

Вот еще одно решение без регулярных выражений, не суперклассное, не супероптимизированное, но очень простое для понимания решение без внешней библиотеки:

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, "/");
person jake_hetfield    schedule 13.02.2012

Вы можете использовать removeStart и removeEnd из Apache Commons Lang StringUtils

person Valentin Rocher    schedule 18.01.2010

Ручная работа по первому варианту:

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

person OscarRyz    schedule 18.01.2010
comment
Босс, в вашей последней строке будет return inString.substring( from , to + 1 ); - person Bipul Roy; 01.08.2018

похоже, что нет готового к использованию java API, который делает это, но вы можете написать метод, который сделает это за вас. эта ссылка может быть полезной

person Ahmed Kotb    schedule 18.01.2010
comment
конечно, это: D я имел в виду функцию обрезки, которая принимает строку, как говорится в вопросе - person Ahmed Kotb; 18.01.2010

EDIT: исправлено ответом, чтобы заменить только первый и последний символы '\'.

System.err.println("\\joe\\jill\\".replaceAll("^\\\\|\\\\$", ""));
person Adamski    schedule 18.01.2010

На самом деле я бы написал свою собственную маленькую функцию, которая делает свое дело, используя простой доступ к char:

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', '\\' );
person x4u    schedule 18.01.2010

Я не думаю, что есть встроенная функция для обрезки на основе переданной строки. Вот небольшой пример того, как это сделать. Это, вероятно, не самое эффективное решение, но, вероятно, оно достаточно быстрое для большинства ситуаций, оцените и адаптируйтесь к вашим потребностям. Я рекомендую тестировать производительность и при необходимости оптимизировать любой фрагмент кода, который будет использоваться регулярно. Ниже я привел некоторую информацию о времени в качестве примера.

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» и т. д.

Некоторое время производительности для запуска каждого из следующих 10 миллионов раз.

" mile ".trim(); выполняется за 248 мс. включена в качестве эталонной реализации для сравнения производительности.

trim( "smiles", "s" ); выполняется за 547 мс — примерно в 2 раза дольше, чем метод String.trim() в Java.

"smiles".replaceAll("s$|^s",""); выполняется за 12 306 мс — примерно в 48 раз дольше, чем метод String.trim() в Java.

А при использовании скомпилированного шаблона регулярного выражения Pattern pattern = Pattern.compile("s$|^s"); pattern.matcher("smiles").replaceAll(""); выполняется за 7804 мс — примерно в 31 раз дольше, чем метод String.trim() в Java.

person Alex B    schedule 18.01.2010
comment
answer.length - trimChar.length - 1 на самом деле - person Brett Widmeier; 18.01.2010
comment
Не очень оптимизирован. Я бы не стал использовать это. - person Pindatjuh; 18.01.2010
comment
@BrettWidmeier Думаю, я написал это. trim( "smiles", "les" ) дает smi, а trim( "smiles", "s" ) дает mile. - person Alex B; 18.01.2010
comment
Я не могу представить более неэффективного способа решения этой проблемы. - person Lawrence Dol; 18.01.2010
comment
@SoftwareMonkey Я согласен, что это не самое эффективное решение, но контекст полезен. На моей машине 10 миллионов запусков trim( "smiles", "s" ); занимают 547 мс, а 10 миллионов запусков " mile ".trim() занимают 248 мс. Мое решение наполовину быстрее, чем String.trim(), и все же 10 миллионов запусков выполняются примерно за полсекунды. - person Alex B; 18.01.2010
comment
@SoftwareMonkey Числа регулярных выражений таковы, что "smiles".replaceAll("s$|^s","") запуск 10 миллионов раз занимает 12 306 мс (~ 48 раз медленнее, чем String.trim() и ~ 24 раза медленнее, чем моя реализация) - person Alex B; 18.01.2010
comment
@Alex: я заберу свой голос против, если вы добавите примечание о том, что его следует оптимизировать для обычного случая обрезки одного символа; Я проголосую за него, если вы измените код, чтобы оптимизировать его (учитывая, что то, что запрашивается, является повторно используемым библиотечным методом). - person Lawrence Dol; 19.01.2010
comment
(и под одним символом я подразумеваю любое количество одного символа с любого конца... IOW, когда длина trimChar равна 1). Кроме того, trimChar - плохое имя для этого параметра... скорее всего, это будет trimString или trimValue. - person Lawrence Dol; 19.01.2010
comment
@SoftwareMonkey: я ценю обратную связь. Я добавлю комментарий об оптимизации для проблемной области, но я не видел никакого контекста того, как это будет использоваться в исходном вопросе или сколько символов будет удалено (в одном примере был один символ, а в одном примере было строка). Хороший призыв к имени trimChar. - person Alex B; 19.01.2010
comment
Ваше сравнение с регулярным выражением не совсем справедливо или реалистично; поскольку используемая форма будет компилировать регулярное выражение каждый раз. Если бы кто-то делал это часто, он бы создал регулярное выражение и повторно использовал сопоставитель, как предлагает JavaDoc: An invocation of this method of the form str.replaceAll(regex, repl) yields exactly the same result as the expression Pattern.compile(regex).matcher(str).replaceAll(repl). - person Lawrence Dol; 19.01.2010
comment
@SoftwareMonkey: Отлично! Я взял пример регулярного выражения из кода @PauloGuedes. Я добавил числа для скомпилированной версии регулярного выражения в свой раздел времени. - person Alex B; 20.01.2010

Вот как бы я это сделал.

Я думаю, что это настолько эффективно, насколько это возможно. Он оптимизирует регистр одного символа и позволяет избежать создания нескольких подстрок для каждой удаляемой подпоследовательности.

Обратите внимание, что крайний случай передачи пустой строки для обрезки обрабатывается (некоторые другие ответы попадут в бесконечный цикл).

/** 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;
    }
person Lawrence Dol    schedule 19.01.2010

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\\\\"
person Max    schedule 09.05.2019

Мое решение:

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;
    }
person David    schedule 15.10.2020