Recortar un carácter específico de una cadena


120

¿Cuál es el equivalente de JavaScript a este C#método?

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

¡C # recorta el carácter seleccionado solo al principio y al final de la cadena!

Respuestas:


155

Una línea es 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

Una solución general:

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


35

Si entendí bien, desea eliminar un carácter específico solo si está al principio o al final de la cadena (por ejemplo, ||fo||oo||||debería convertirse foo||oo). Puede crear una función ad hoc de la siguiente manera:

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

Probé esta función con el siguiente código:

var str = "|f|oo||";
$( "#original" ).html( "Original String: '" + str + "'" );
$( "#trimmed" ).html( "Trimmed: '" + trimChar(str, "|") + "'" );

3
Esta sería una prueba divertida para el recolector de basura, pero no recomendaría someter a sus clientes a ella.
Sorensen

18

Puede utilizar una expresión regular como:

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

ACTUALIZAR:

Si desea generalizar esto en una función, puede hacer lo siguiente:

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

17

para mantener esta pregunta actualizada:

aquí hay un enfoque que elegiría sobre la función regex usando el operador de propagación 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);
}

Versión mejorada después del comentario de @fabian (puede manejar cadenas que contienen solo el mismo carácter)

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

2
Sé que las expresiones regulares son excesivas aquí, pero ¿por qué elegiría esta implementación en particular?
Nicholas Shanks

2
esta implementación porque personalmente la encuentro bien legible. sin expresiones regulares simplemente porque el "árbol" de decisiones dentro de los motores de expresiones regulares es mucho más grande. y especialmente porque las expresiones regulares utilizadas para recortar contienen caracteres de consulta que conducen a retroceder dentro del motor de expresiones regulares. estos motores a menudo compilan el patrón en código de bytes, asemejándose a instrucciones de máquina. el motor luego ejecuta el código, saltando de instrucción en instrucción. cuando una instrucción falla, retrocede para encontrar otra forma de hacer coincidir la entrada. ergo hay muchas más cosas que nec.
Robin F.

Gracias por responder, aunque quería que me explicaras por qué elegirías esto en lugar de otras formas de hacerlo que no son expresiones regulares, esperaba más que simplemente "Lo encuentro legible", supongo.
Nicholas Shanks

1
@RobinF. ¿Crees que findIndex () y reverse () no contienen bucles? Piensa otra vez.
Andrew

1
Dos anotaciones: una cadena que contenga solo el carácter que se va a recortar no se recortará en absoluto. El otro punto es: la explosión de la cadena en una matriz con el operador de propagación confundirá a babel y la transformará en lo [].concat(string)que no es el resultado deseado. El uso Array.from(string)funcionará.
Fabian

14

Una versión sin expresiones regulares que es agradable a la vista:

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

Para casos de uso en los que estamos seguros de que no hay repetición de los caracteres en los bordes.


bastante interesante ... así que split devuelve un elemento indefinido por igual a cada delimitador que se divideconst 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

Si está tratando con cadenas más largas, creo que esto debería superar a la mayoría de las otras opciones al reducir el número de cadenas asignadas a cero o uno:

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'

O si desea recortar de un conjunto de varios 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 divertirse, recorta palabras (en lugar de caracteres individuales)

// 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');

1
Prefiero esta solución porque, de hecho, es realmente eficiente, en lugar de solo breve.
tekHedd

Estoy de acuerdo en que debería preferirse. Reemplaza una respuesta que había dado.
TamusJRoyce

9

Esto puede recortar varios caracteres a la 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

@fubo: No, en realidad no. Es una demostración, si la pega en una consola, simplemente imprimirá el resultado. Pero entiendo que puede resultar confuso, así que lo he editado.
marlar

2

Si define estas funciones en su programa, sus cadenas tendrán una versión mejorada trimque puede recortar todos los caracteres dados:

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)

Fuente

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


1

Que yo sepa, jQuery no tiene una función incorporada en el método por el que está preguntando. Sin embargo, con javascript, puede usar reemplazar para cambiar el contenido de su cadena:

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

Esto reemplazará todas las apariciones de | sin nada.


¿Hay alguna manera de eliminar? solo al principio / final?
fubo

De hecho, creo que esta publicación lo pondrá al día al máximo sobre su pregunta: stackoverflow.com/questions/20196088/…
Ole Haugset

@fubo Claro ... Agregue algo $así solo al final: "||spam|||".replace(/\|+$/g, "")o uno ^así solo al comienzo:"||spam|||".replace(/^\|+/g, "")
ruffin

1

Éste recorta todos los delímetros iniciales y finales

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

1

Sugeriría mirar lodash y cómo implementaron el trim función.

Consulte Lodash Trim para obtener la documentación y la fuente. para ver el código exacto que realiza el recorte.

Sé que esto no proporciona una respuesta exacta a su pregunta, pero creo que es bueno establecer una referencia a una biblioteca en una pregunta de este tipo, ya que otros pueden encontrarla útil.


1
@TamusJRoyce no es el mismo
gdbdable

@devi Solo puedo estar de acuerdo. gracias por el comentario. buena respuesta buscando en una herramienta apoyada por la comunidad.
TamusJRoyce

1

La mejor manera de resolver esta tarea es (similar a la trimfunción 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>

PD: ¿Por qué publiqué mi respuesta, cuando la mayoría de la gente ya lo hizo antes? Porque encontré "el mejor" error en todas las respuestas: todos usaron el meta '+' en lugar de '*', porque trimdeben eliminar los caracteres SI ESTÁN EN INICIO Y / O FIN, pero devuelve la cadena original en el otro caso .


0

expandiendo la respuesta de @leaf, aquí hay uno que puede tomar varios 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
}

0

Me gusta la solución de @ Pho3niX83 ...

Extendamos con "palabra" en lugar 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);
};

0
function trim(text, val) {
    return text.replace(new RegExp('^'+val+'+|'+val+'+$','g'), '');
}



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

Solo elimina una aparición, pero no se recorta hasta que el personaje está completamente recortado
KoalaBear

1
No anule el prototipo de cadena predeterminado o tendrá problemas más adelante. Cree sus propias funciones independientes en otro lugar.
Rooby

-2

Prueba este método:

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


1
¿Por qué? ¿Qué hace esto? ¿Como funciona? Las respuestas de solo código se consideran de baja calidad en SO. Explique su respuesta para que OP y los futuros visitantes puedan aprender de ella.
Que no cunda el pánico
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.