Apara caractere específico de uma string

120

Qual é o JavaScript equivalente a este C#método:

var x = "|f|oo||"; 
var y = x.Trim('|'); //  "f|oo"

C # apara o caractere selecionado apenas no início e no final da string!

fubo
fonte

Respostas:

155

Uma linha é suficiente:

var x = '|f|oo||';
var y = x.replace(/^\|+|\|+$/g, '');
document.write(x + '<br />' + y);

^\|+   beginning of the string, pipe, one or more times
|      or
\|+$   pipe, one or more times, end of the string

Uma solução geral:

function trim (s, c) {
  if (c === "]") c = "\\]";
  if (c === "\\") c = "\\\\";
  return s.replace(new RegExp(
    "^[" + c + "]+|[" + c + "]+$", "g"
  ), "");
}

chars = ".|]\\";
for (c of chars) {
  s = c + "foo" + c + c + "oo" + c + c + c;
  console.log(s, "->", trim(s, c));
}

folha
fonte
35

Se bem entendi, você deseja remover um caractere específico apenas se estiver no início ou no final da string (ex: ||fo||oo||||deve se tornar foo||oo). Você pode criar uma função ad hoc da seguinte maneira:

function trimChar(string, charToRemove) {
    while(string.charAt(0)==charToRemove) {
        string = string.substring(1);
    }

    while(string.charAt(string.length-1)==charToRemove) {
        string = string.substring(0,string.length-1);
    }

    return string;
}

Testei essa função com o código abaixo:

var str = "|f|oo||";
$( "#original" ).html( "Original String: '" + str + "'" );
$( "#trimmed" ).html( "Trimmed: '" + trimChar(str, "|") + "'" );
Pho3niX83
fonte
3
Este seria um teste divertido para o coletor de lixo, mas eu não recomendaria submeter seus clientes a ele.
Sorensen de
18

Você pode usar uma expressão regular, como:

var x = "|f|oo||";
var y = x.replace(/^[\|]+|[\|]+$/g, "");
alert(y); // f|oo

ATUALIZAR:

Se você deseja generalizar isso em uma função, você pode fazer o seguinte:

var escapeRegExp = function(strToEscape) {
    // Escape special characters for use in a regular expression
    return strToEscape.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
};

var trimChar = function(origString, charToTrim) {
    charToTrim = escapeRegExp(charToTrim);
    var regEx = new RegExp("^[" + charToTrim + "]+|[" + charToTrim + "]+$", "g");
    return origString.replace(regEx, "");
};

var x = "|f|oo||";
var y = trimChar(x, "|");
alert(y); // f|oo
Neelsg
fonte
17

para manter esta questão atualizada:

aqui está uma abordagem que eu escolheria em vez da função regex usando o operador de propagação ES6.

function trimByChar(string, character) {
  const first = [...string].findIndex(char => char !== character);
  const last = [...string].reverse().findIndex(char => char !== character);
  return string.substring(first, string.length - last);
}

Versão melhorada após o comentário de @fabian (pode lidar com strings contendo apenas o mesmo caractere)

function trimByChar(string, character) {
  const arr = Array.from(string);
  const first = arr.indexOf(character);
  const last = arr.reverse().indexOf(character);
  return string.substring(first + 1, string.length - last - 1);
}
Robin F.
fonte
2
Eu sei que regexes são um exagero aqui, mas por que você escolheria essa implementação específica?
Nicholas Shanks,
2
esta implementação porque pessoalmente a considero bem legível. sem regex simplesmente porque a "árvore" de decisão nos motores de regex é muito maior. e especialmente porque os regexes usados ​​para corte contêm caracteres de consulta que levam ao retrocesso no mecanismo de regex. esses mecanismos frequentemente compilam o padrão em código de bytes, semelhante a instruções de máquina. o motor então executa o código, saltando de uma instrução para outra. quando uma instrução falha, ele então retorna para encontrar outra maneira de combinar a entrada. logo, muito mais acontecendo do que nec.
Robin F.
Obrigado por responder, embora eu queira que você explique por que você escolheu isso em vez de outras formas não regex de fazer isso - eu esperava mais do que apenas "Acho legível", suponho.
Nicholas Shanks
1
@RobinF. você acha que findIndex () e reverse () não contém loops? Pense de novo.
Andrew,
1
Duas anotações: Uma string contendo apenas o caractere a ser aparado não será aparada. O outro ponto é: explodir a string em uma matriz com o operador de propagação confundirá babel e a transformará em algo [].concat(string)que não seja o desejado. Usar Array.from(string)vai funcionar.
Fabian
14

Uma versão sem regex que é agradável à vista:

const trim = (str, chars) => str.split(chars).filter(Boolean).join(chars);

Para casos de uso em que temos certeza de que não há repetição dos caracteres nas bordas.

mbaer3000
fonte
bastante interessante ... então a divisão retorna o elemento indefinido para igual a cada delimitador que é divididoconst trim = (str, chars) => str.split(chars).filter(x => { Boolean(x); console.log(typeof(x), x, Boolean(x)); }).join(chars); const str = "#//#//abc#//test#//end#//"; console.log(trim(str, '#//'));
TamusJRoyce
10

Se você estiver lidando com strings mais longas, acredito que isso deve superar a maioria das outras opções, reduzindo o número de strings alocadas para zero ou um:

function trim(str, ch) {
    var start = 0, 
        end = str.length;

    while(start < end && str[start] === ch)
        ++start;

    while(end > start && str[end - 1] === ch)
        --end;

    return (start > 0 || end < str.length) ? str.substring(start, end) : str;
}

// Usage:
trim('|hello|world|', '|'); // => 'hello|world'

Ou se você quiser cortar um conjunto de vários caracteres:

function trimAny(str, chars) {
    var start = 0, 
        end = str.length;

    while(start < end && chars.indexOf(str[start]) >= 0)
        ++start;

    while(end > start && chars.indexOf(str[end - 1]) >= 0)
        --end;

    return (start > 0 || end < str.length) ? str.substring(start, end) : str;
}

// Usage:
trimAny('|hello|world   ', [ '|', ' ' ]); // => 'hello|world'
// because '.indexOf' is used, you could also pass a string for the 2nd parameter:
trimAny('|hello| world  ', '| '); // => 'hello|world'

EDITAR: Para se divertir, corte palavras (em vez de caracteres individuais)

// Helper function to detect if a string contains another string
//     at a specific position. 
// Equivalent to using `str.indexOf(substr, pos) === pos` but *should* be more efficient on longer strings as it can exit early (needs benchmarks to back this up).
function hasSubstringAt(str, substr, pos) {
    var idx = 0, len = substr.length;

    for (var max = str.length; idx < len; ++idx) {
        if ((pos + idx) >= max || str[pos + idx] != substr[idx])
            break;
    }

    return idx === len;
}

function trimWord(str, word) {
    var start = 0,
        end = str.length,
        len = word.length;

    while (start < end && hasSubstringAt(str, word, start))
        start += word.length;

    while (end > start && hasSubstringAt(str, word, end - len))
        end -= word.length

    return (start > 0 || end < str.length) ? str.substring(start, end) : str;
}

// Usage:
trimWord('blahrealmessageblah', 'blah');
Jason Larke
fonte
1
Prefiro essa solução porque ela é, de fato, eficiente, e não apenas curta.
tekHedd
Eu concordo que deveria ser preferido. Substitui uma resposta que eu dei.
TamusJRoyce
9

Isso pode cortar vários caracteres de uma vez:

String.prototype.trimChars = function (c) {
  var re = new RegExp("^[" + c + "]+|[" + c + "]+$", "g");
  return this.replace(re,"");
}

var x = "|f|oo||"; 
x =  x.trimChars('|'); // f|oo

var y = "..++|f|oo||++..";
y = y.trimChars('|.+'); // f|oo

var z = "\\f|oo\\"; // \f|oo\

// For backslash, remember to double-escape:
z = z.trimChars("\\\\"); // f|oo
marlar
fonte
@fubo: Não, na verdade não. É uma demonstração, se você colar em um console, apenas imprimirá o resultado. Mas eu entendo que pode ser confuso, então eu editei.
marlar
2

Se você definir essas funções em seu programa, suas strings terão uma versão atualizada trimque pode cortar todos os caracteres fornecidos:

String.prototype.trimLeft = function(charlist) {
	if (charlist === undefined)
	charlist = "\s";

	return this.replace(new RegExp("^[" + charlist + "]+"), "");
};

String.prototype.trim = function(charlist) {
	return this.trimLeft(charlist).trimRight(charlist);
};

String.prototype.trimRight = function(charlist) {
	if (charlist === undefined)
	charlist = "\s";

	return this.replace(new RegExp("[" + charlist + "]+$"), "");
};

var withChars = "/-center-/"
var withoutChars = withChars.trim("/-")
document.write(withoutChars)

Fonte

https://www.sitepoint.com/trimming-strings-in-javascript/

Chris Redford
fonte
1

Que eu saiba, o jQuery não tem uma função incorporada ao método que você está perguntando. Com o javascript, no entanto, você pode apenas usar substituir para alterar o conteúdo da sua string:

x.replace(/|/i, ""));

Isso substituirá todas as ocorrências de | com nada.

Ole Haugset
fonte
existe uma maneira de remover | apenas no início / fim?
fubo,
Na verdade, acho que este post irá ajudá-lo a entender melhor sua pergunta: stackoverflow.com/questions/20196088/…
Ole Haugset
@fubo Claro ... Jogue $assim para apenas no final: "||spam|||".replace(/\|+$/g, "")ou ^assim para apenas no início:"||spam|||".replace(/^\|+/g, "")
ruffin de
1

Este corta todos os delimitadores anteriores e posteriores

const trim = (str, delimiter) => {
  const pattern = `[^\\${delimiter}]`;
  const start = str.search(pattern);
  const stop = str.length - str.split('').reverse().join('').search(pattern);
  return str.substring(start, stop);
}

const test = '||2|aaaa12bb3ccc|||||';
console.log(trim(test, '|')); // 2|aaaa12bb3ccc
Dmitriy Botov
fonte
1

Eu sugeriria olhar para Lodash e como eles implementaram a trimfunção.

Consulte Lodash Trim para a documentação e a fonte para ver o código exato que faz o corte.

Sei que isso não fornece uma resposta exata à sua pergunta, mas acho bom definir uma referência para uma biblioteca sobre essa questão, pois outros podem achar útil.

drew7721
fonte
1
@TamusJRoyce não é o mesmo
gdbdable
@devi Eu só posso concordar. Obrigado pelo comentário. boa resposta procurando uma ferramenta com suporte da comunidade.
TamusJRoyce
1

A melhor maneira de resolver essa tarefa é (semelhante à trimfunção PHP ):

function trim( str, charlist ) {
  if ( typeof charlist == 'undefined' ) {
    charlist = '\\s';
  }
  
  var pattern = '^[' + charlist + ']*(.*?)[' + charlist + ']*$';
  
  return str.replace( new RegExp( pattern ) , '$1' )
}

document.getElementById( 'run' ).onclick = function() {
  document.getElementById( 'result' ).value = 
  trim( document.getElementById( 'input' ).value,
  document.getElementById( 'charlist' ).value);
}
<div>
  <label for="input">Text to trim:</label><br>
  <input id="input" type="text" placeholder="Text to trim" value="dfstextfsd"><br>
  <label for="charlist">Charlist:</label><br>
  <input id="charlist" type="text" placeholder="Charlist" value="dfs"><br>
  <label for="result">Result:</label><br>
  <input id="result" type="text" placeholder="Result" disabled><br>
  <button type="button" id="run">Trim it!</button>
</div>

PS: por que postei minha resposta, quando a maioria das pessoas já fez isso antes? Porque eu encontrei "o melhor" erro em todas as respostas: todas usaram a meta '+' em vez de '*', porque trimdeve remover os caracteres SE ELES ESTÃO NO INÍCIO E / OU FIM, mas retorna a string original em caso contrário .

StoneCountry
fonte
0

expandindo a resposta de @leaf, aqui está uma que pode ter vários caracteres:

var trim = function (s, t) {
  var tr, sr
  tr = t.split('').map(e => `\\\\${e}`).join('')
  sr = s.replace(new RegExp(`^[${tr}]+|[${tr}]+$`, 'g'), '')
  return sr
}
AmitK
fonte
0

Gosto da solução de @ Pho3niX83 ...

Vamos estendê-lo com "palavra" em vez de "char" ...

function trimWord(_string, _word) {

    var splitted = _string.split(_word);

    while (splitted.length && splitted[0] === "") {
        splitted.shift();
    }
    while (splitted.length && splitted[splitted.length - 1] === "") {
        splitted.pop();
    }
    return splitted.join(_word);
};
raposa
fonte
0
function trim(text, val) {
    return text.replace(new RegExp('^'+val+'+|'+val+'+$','g'), '');
}
Alexandre Ladonin
fonte
0
"|Howdy".replace(new RegExp("^\\|"),"");

(observe o escape duplo. \\necessário, para ter uma barra realmente única na string , que leva ao escape de |no regExp ).

Apenas alguns caracteres precisam de regExp-Escaping. , entre eles o operador de tubos.

Frank Nocke
fonte
-1

experimentar:

console.log(x.replace(/\|/g,''));
Man Programmer
fonte
-1
String.prototype.TrimStart = function (n) {
    if (this.charAt(0) == n)
        return this.substr(1);
};

String.prototype.TrimEnd = function (n) {
    if (this.slice(-1) == n)
        return this.slice(0, -1);
};
Tobo
fonte
Ele remove apenas uma ocorrência, mas não apara até que o caractere seja totalmente aparado
KoalaBear
1
Não substitua o protótipo de string padrão ou você terá problemas mais tarde. Crie suas próprias funções separadas em outro lugar.
rooby de
-2

Experimente este método:

var a = "anan güzel mi?";
if (a.endsWith("?"))   a = a.slice(0, -1);  
document.body.innerHTML = a;

Ali CAKIL
fonte
1
Por quê? O que isso faz? Como funciona? Respostas apenas em código são consideradas de baixa qualidade no SO. Explique sua resposta para que o OP e quaisquer futuros visitantes possam aprender com ela.
Não entre em pânico,