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!

fubo
fuente

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

hoja
fuente
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, "|") + "'" );
Pho3niX83
fuente
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
neelsg
fuente
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);
}
Robin F.
fuente
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.

mbaer3000
fuente
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');
Jason Larke
fuente
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
marlar
fuente
@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/

Chris Redford
fuente
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.

Ole Haugset
fuente
¿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
Dmitriy Botov
fuente
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.

drew7721
fuente
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 .

PiedraPaís
fuente
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
}
AmitK
fuente
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);
};
foxontherock
fuente
0
function trim(text, val) {
    return text.replace(new RegExp('^'+val+'+|'+val+'+$','g'), '');
}
Alexander Ladonin
fuente
0
"|Howdy".replace(new RegExp("^\\|"),"");

(tenga en cuenta el doble escape. \\necesario, para tener una barra diagonal única en la cadena , que luego conduce al escape |en el regExp ).

Solo unos pocos caracteres necesitan regExp-Escaping. , entre ellos el operador de tuberías.

Frank Nocke
fuente
-1

tratar:

console.log(x.replace(/\|/g,''));
Programador hombre
fuente
-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
fuente
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;

Ali CAKIL
fuente
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