如何使用 javascript regexp 替换字符串的一部分

Posted

技术标签:

【中文标题】如何使用 javascript regexp 替换字符串的一部分【英文标题】:How to replace part of a string using javascript regexp 【发布时间】:2020-04-20 13:29:45 【问题描述】:

我有这段文字需要替换css的宽度部分:

oldStyle = "width:90%;height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;"

我有这个代码表达式或模式:

oldStyle.replace(new RegExp("width:[0-9]+%;.*$", "g"), "width:25%;")

但结果是:

"width:25%;"

它缺少 css 的其余部分:

"height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;"

结果应该是:

"width:25%;height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;"

如何只更改 CSS 的宽度部分并保持其他 CSS 的其余部分不变?

【问题讨论】:

为什么不使用简单的字符串操作而不是正则表达式? 试试new RegExp("width:[0-9]+%;", "g") 我还有其他依赖此方法的代码 JB31 没问题,但如果 oldStyle 有 max-width:40%;这也会改变最大宽度 (?:^|;|\s)width:[0-9]+(?:px|%) 是否用作正则表达式? 【参考方案1】:

您不需要为此任务使用正则表达式。还有更简单的选择。

基本的字符串操作

function changeWidth(style, newValue) 
  const segments = style
    .slice(0, -1) //remove last `;`
    .split(';');
    
  const nonWidthSegments = segments.filter(segment => !segment.startsWith("width"));
  
  return nonWidthSegments
    .concat(`width: $newValue`)
    .join(';')
    .concat(';'); //add the last `;`


console.log(changeWidth(
  "width:90%;height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;",  
  "45px"
));


console.log(changeWidth(
  "margin: auto;",  
  "45px"
));


console.log(changeWidth(
  "",  
  "45px"
));

DOM 操作

function changeWidth(style, newValue) 
  const el = document.createElement("div");
  
  el.setAttribute("style", style);
  
  el.style.width = newValue;
  
  return el.getAttribute("style");


console.log(changeWidth(
  "width:90%;height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;",  
  "45px"
));

console.log(changeWidth(
  "margin: auto;",  
  "45px"
));

console.log(changeWidth(
  "",  
  "45px"
));

只是想更新 VLAZ 建议的答案,经过更多测试后,此代码实际上因 .startsWith 函数而失败,因为假设您想更改 border-bottom-left-radius 并且通过的旧样式具有旧样式border-bottom,那么这将过滤掉旧样式变量中的border-bottom,而不是添加或更新border-bottom-left-radius

所以我稍微修改了函数,仍然采用 VLAZ 的建议: 传递的键是样式属性,例如 borderborder-topwidth 或任何其他样式属性。

刚刚进一步编辑,因为newStyle 部分没有通过newValue

function changeWidth(oldStyle, newValue, key) 

const segments = oldStyle
        .slice(0, -1) //remove last `;`
        .split(';');
    
    var matchSegement = "";
    for (var t = 0; t < segments.length; t++) 
        if (segments[t].split(":")[0] == key) 
            matchSegement = segments[t];
        
    

    var nonWidthSegments = segments.filter(function (segment) 
        return segment != matchSegement;
    );

    var newStyle = nonWidthSegments
        .concat(key + `:$newValue`)
        .join(';')
        .concat(';'); 


【讨论】:

他想使用regexp,而不是其他方法 @AhmetZeybek 我发现很多人想使用正则表达式,因为他们不知道任何其他方式。许多未来的访问者也可能会从了解 regex 不是金锤中受益。 @AhmetZeybek 如果你想知道我为什么喜欢给出替代方案的原因,那么你会注意到这里的每一个正则表达式答案都是错误的。不是正则表达式无法正确编写,而是很容易错误地编写它 最后我使用了 VLAZ 方法,我使用 regexp 尝试了其他建议,但是当我添加 VLAZ 已回答的代码时,它很容易设置并集成到我的代码中,我让它完全正常工作现在。感谢大家的建议,但感谢 VLAZ 对其进行了排序!我会赞成其他建议和答案,因为它帮助我更多地理解正则表达式,但这是我一直在寻找的答案。【参考方案2】:

您可以使用下面的正则表达式来实现您想要的。正则表达式将用%pxrem 和许多其他单位替换任何宽度;

string = "width:90%;height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;"
console.log(string.replace(/width ?: ?[0-9]+(%|[a-z]+|);/ig,"width:25%;"))

【讨论】:

如果单位不是%pxrem怎么办?有many other units,也有可能没有单位。或者你甚至可能有width: auto。这将在更多成功的情况下失败。 我已经更新了代码,在这种情况下它仍然可以工作。【参考方案3】:

这将更改字符串中以width 开头并以%; 结尾的任何值,您可以根据需要修改正则表达式

first = "width:90%;height:100%;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;"
second = "width:90%;height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;"
third = "height:inherit;padding-right: 15px;padding-left: 15px;width:90%;margin-right: auto;margin-left: auto;"

console.log(first.replace(/width(.*?);/g,"width:25%;"))
console.log(second.replace(/width(.*?);/g,"width:25%;"))
console.log(third.replace(/width(.*?);/g,"width:25%;"))

【讨论】:

有many units,而不仅仅是%。如果值是90px,那么这很有可能会失败。在width: 90px; height: 100%; 的情况下,这可能是灾难性的胜利——height 属性将使用这个正则表达式被清除。 @VLAZ 是的,我忘了输入? 字符,现在它可以正常工作了。【参考方案4】:

仅将数值 width:90px; 替换为 width:40px;

width:90%;width:40%;

str = "max-width:40px;width:90px;height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;"
console.log(str.replace(/([^-]width)(:[0-9]\d+)(.*)/g,"$1:25$3"))

str = "max-width:40px;width:90%;height:inherit;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;"
console.log(str.replace(/([^-]width)(:[0-9]\d+)(.*)/g,"$1:25$3"))

【讨论】:

【参考方案5】:

这部分width:[0-9]+%; 会找到一些百分比的宽度值,但是这部分.*$ 匹配“直到字符串末尾的任何内容”。

但你不希望第二部分被width:25%; 替换,所以,直接放弃吧:

oldStyle.replace(new RegExp("width:[0-9]+%;", "g"), "width:25%;")

这个 RegExp 肯定会得到改进。正如人们在 cmets 中正确指出的那样,例如,它也将匹配 max-width:75% 并随后将其更改为 max-width:25%。 但是,根据您的用例,它可能就足够了。

一般来说,考虑到可能出错的事情的数量,您希望在这种情况下避免使用 RegExp,直到您有其他选择。

【讨论】:

有many units,而不仅仅是%。这完全有可能失败,特别是如果您使用 width: 90% 之类的东西 - 带有空格。 @VLAZ 我们不知道实际用例是什么,只有作者知道。 he 为什么在他的 RegExp 中使用了 %。可能,他只想替换带有百分比的值。

以上是关于如何使用 javascript regexp 替换字符串的一部分的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript RegExp 对象

JavaScript初识正则-RegExp

javascript类型系统——正则表达式RegExp类型

如何使用 REGEXP_REPLACE 替换特定条件下的重复单词?

javascript类型系统——正则表达式RegExp类型

JavaScript RegExp 对象