如何去除字符串周围的特定字符?

16

我有这个字符串:

var str = "? this is a ? test ?";

现在我想得到这个:

var newstr = "this is a ? test";
如您所见,我想仅删除围绕字符串的那些?(在开头和结尾处,而不是字符串中间)。如何使用JavaScript实现此操作?
这是我尝试过的代码:
var str = "? this is a ? test ?";
var result = str.trim("?");
document.write(result);

所以,你看到它不起作用。实际上,我是一名PHP开发人员,trim()在PHP中运行良好。现在我想知道是否可以在JS中使用trim()来做到这一点。


应该注意我可以使用正则表达式来做到这一点,但老实说我讨厌正则表达式用于此类工作。无论如何,有更好的解决方案吗?


编辑:正如评论中提到的那样,我需要删除字符串周围的?和空格。


我现在意识到了。为什么不将0,1length-1,length分割成子字符串,并扫描?(并删除空格),然后将这些字符串连接回主字符串呢? - AStopher
@Kyll 我想要移除字符串周围的问号和空格。 - Shafizadeh
1
@Shafizadeh,你的字符串开头和结尾会有任意数量的 ? 吗?还是只是 ? [文本] ? - AStopher
2
这真的很不清楚。??? Test ??Test ?? ??? Test ?? ? 或其他组合应该输出什么? - Tunaki
2
投票重新开放。我仍然无法理解为什么现实世界中的人们可以成为高级人员,却投票关闭一个如此易于理解的编程问题。 - John
显示剩余7条评论
10个回答

16

查找字符掩码并返回其余部分。

该提案建议使用按位非 ~ 运算符进行检查。

~ is a bitwise not operator. It is perfect for use with indexOf(), because indexOf returns if found the index 0 ... n and if not -1:

value  ~value   boolean
 -1  =>   0  =>  false
  0  =>  -1  =>  true
  1  =>  -2  =>  true
  2  =>  -3  =>  true
  and so on 

function trim(s, mask) {
    while (~mask.indexOf(s[0])) {
        s = s.slice(1);
    }
    while (~mask.indexOf(s[s.length - 1])) {
        s = s.slice(0, -1);
    }
    return s;
}

console.log(trim('??? this is a ? test ?', '? '));
console.log(trim('abc this is a ? test abc', 'cba '));


不错,但使用两个修剪索引并在最后一次执行slice会更有效率。 - georg
@georg,如果索引重叠,需要进行另一个测试。 - Nina Scholz
一个问题,~ 在 JS 中的意思是什么? - Shafizadeh
@Shafizadeh,这是一个按位非运算符,请参见编辑。 - Nina Scholz
感谢您的解释。 - Mostafa Lavaei
显示剩余4条评论

7

只需简单使用:

let text = '?? something ? really ??'
text = text.replace(/^([?]*)/g, '')
text = text.replace(/([?]*)$/g, '')

console.log(text)


6
一种可能的解决方案是使用递归函数来删除不需要的前后字符,这种方法不使用正则表达式。
function ltrim(char, str) {
    if (str.slice(0, char.length) === char) {
        return ltrim(char, str.slice(char.length));
    } else {
        return str;
    }
}

function rtrim(char, str) {
    if (str.slice(str.length - char.length) === char) {
        return rtrim(char, str.slice(0, 0 - char.length));
    } else {
        return str;
    }
}

当然,这只是众多可能解决方案之一。函数trim将同时使用ltrimrtrimchar作为第一个参数,需要清理的字符串作为第二个参数,其原因在于使其更容易转换成函数式编程风格的函数,例如(ES 2015):
function ltrim(char) {
    (str) => {
        <body of function>
    }
}

// No need to specify str here
function ltrimSpaces = ltrim(' ');

PHP的trim函数也可以使用trim("??string??", "??") // string. - Xorifelse
@Xorifelse:我更新了我的答案,现在可以修剪多字符字符串。 - Arjan
@cybermonkey:如果你不想复制 PHP 中存在但 JavaScript 中不存在的行为(并且不想依赖已经为你完成工作的库),那么你可能需要对一个 PHP 脚本进行(ajax)调用。 - Arjan
1
@cybermonkey 绝对没错。如果可能的话,应该在客户端上完成。(并且对于需要存储在某处的数据,还要在服务器上再次进行处理,因为来自任何客户端的数据都必须被视为不安全的。) - Arjan
@Arjan 现在是下一个,trim函数默认情况下(未提交参数)会自动剪切以下字符:'\n'(换行符),'\r'(回车符),'\t'(制表符),'\v'(垂直制表符),'\0'(空字符) - Xorifelse
显示剩余5条评论

4

以下是一种方法,它会检查索引越界并且只调用了一次 substring

String.prototype.trimChars = function(chars) {
  var l = 0;
  var r = this.length-1;
  while(chars.indexOf(this[l]) >= 0 && l < r) l++;
  while(chars.indexOf(this[r]) >= 0 && r >= l) r--;
  return this.substring(l, r+1);
};

例子:

var str = "? this is a ? test ?";

str.trimChars(" ?");  // "this is a ? test"

3

使用简单方法,利用Array.indexOfArray.lastIndexOfArray.slice函数:

更新:(注意:作者要求修剪周围的字符)

function trimChars(str, char){
    var str = str.trim();

    var checkCharCount = function(side) {
        var inner_str = (side == "left")? str : str.split("").reverse().join(""),
            count = 0;

        for (var i = 0, len = inner_str.length; i < len; i++) {
            if (inner_str[i] !== char) {
                break;
            }
            count++;
        }
        return (side == "left")? count : (-count - 1);
    };

    if (typeof char === "string" 
            && str.indexOf(char) === 0
            && str.lastIndexOf(char, -1) === 0) {
        str = str.slice(checkCharCount("left"), checkCharCount("right")).trim();
    }

    return str;
}

var str = "???? this is a ? test ??????";

console.log(trimChars(str, "?"));   // "this is a ? test"

2
不知道这个答案是否正确,但很高兴看到有人真正阅读了问题(之前的四五个答案没有阅读并被删除或/和投票降低)。 - AStopher
@Webeno,我不这么认为,因为初始字符串可能是“?a this is a ? test a?” - RomanPerekhrest
2
@squint,我不认为这个问题含糊不清.. 我想要的只是一个像 PHP 中的trim()函数一样的函数。 - Shafizadeh
1
如果问题不含糊,你也不会因为做出不同的假设而得到不同的答案。据我们所知,如果你有"? ? foo ? bar ? ?",你可能需要保留两端中间的第二个?。结果应该是"foo ? bar"还是"? foo ? bar ?"呢? - user1106925
1
@squint 是的,你说得对……我的问题确实有点模糊……!我希望能够得到 这个 例子的输出结果。 - Shafizadeh
显示剩余5条评论

3

无正则表达式:

uberTrim = s => s.length >= 2 && (s[0] === s[s.length - 1])?
  s.slice(1, -1).trim() 
  : s;

步骤说明:

  1. 检查字符串长度是否至少为2个字符,并且是否被特定字符包围;
  2. 如果是,则先切片以删除周围的字符,然后修剪以删除空格;
  3. 如果不是,则直接返回。

如果您对该语法感到奇怪,它是一个箭头函数和一个三元运算符
顺便说一下,三元运算符中的括号是多余的。

示例用法:

uberTrim(''); // ''
uberTrim(' Plop! '); //'Plop!'
uberTrim('! ...What is Plop?!'); //'...What is Plop?'

3
请注意,这段代码期望前后各有两个字符(总计四个),因此它不会将 '!! Plop !!' 的所有 '!' 和空格都去掉,最终的结果是 '! Plop !' - Kyll

2

使用正则表达式

'? this is a ? test ?'.replace(/^[? ]*(.*?)[? ]*$/g, '$1')

你可能不喜欢正则表达式,但在找到解决方案后,你会感觉很酷 :)

2
为了使用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);
}

1
Javascript的trim方法只能去除空格,并且不带参数。如果需要自定义trim,您将需要编写自己的函数。使用正则表达式可以快速解决此问题,如果您不想麻烦地创建正则表达式,则可以在w3schools上找到一个实现自定义trim的示例(您只需将其调整为过滤?而不是空格)。

-1
这是一行代码,可以返回您想要的输出:
"? this is a ? test ?".slice(1).slice(0,-1).trim();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接