英文:
.replace() won't replace every instance despite /g
问题
我有两个问题与我的JavaScript代码有关。我将尽量保持简洁,只复制与问题有关的部分。
我有以下HTML代码(每个
<li>
<span style="font-family:arial, helvetica, sans-serif">Siehe <a href="Link 1" rel="">Text 1</a>.</span>
</li>
<li>
<span style="font-family:arial, helvetica, sans-serif">Siehe</span> <a href="Link 1" rel="">Text 2</a>.<span style="font-family:arial, helvetica, sans-serif"> </span>
</li>
<li>
Siehe <a href="Link 1" rel="">Text 3</a>.
</li>
以下是我问题所需的JavaScript代码。首先,我删除了每个元素。然后,我想替换"a href"部分并增加新字符串的编号。
var neu = document.getElementById("ausgabe").value;
var nummer = 0;
function getNextDlcNumber() {
return ++nummer;
}
var ersetzen = neu
.replace(/<span.*?>(.*?)<\/span>/g, "$1") // 去除所有span
.replace(/\s<li>\n\s\sSiehe\s*<a href=".*?" rel="">(.*?)<\/a>.\n\s<\/li>/g, "\t<li>\n\t\tSiehe <a class=\"trophiesAnkerLink\" href=\"#dlc\" + getNextDlcNumber() + "\"\" rel=\"\">$1</a>.\n\t</li>")); // 用递增的dlc编号替换a href
document.getElementById("ausgabe").value = ersetzen;
这里有两个问题:
-
第一个和第三个"a href"已成功替换,但第二个没有替换,我无法弄清原因。我认为这与"Siehe"和"a"标签开始之间的span标签有关,但是由于第一个替换应该删除span,所以我不确定这是否是问题的原因。我尝试使用"Siehe\s*<a"、"Siehe <a"以及包含""的"|",但都没有成功。
-
"#dlc"后面的数字没有递增,即使是第三个也只是"#dlc1"。我需要以不同的方式做吗?
这是使用JS后的输出:
<li>
Siehe <a class="trophiesAnkerLink" href="#dlc1" rel="">Text 1</a>.
</li>
<li>
Siehe <a href="Link 1" rel="">Text 2</a>.
</li>
<li>
Siehe <a class="trophiesAnkerLink" href="#dlc1" rel="">Text 3</a>.
</li>
希望我提供了足够的信息。如果不够,我可以提供更多。先谢谢你的帮助
英文:
So, I've got two problems with my javascript code. I'll try to make it as short as possible and only copy parts that are necessary for the problem.
I have this html code (it's not my fault that every li looks different):
<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe <a href="Link 1" rel="">Text 1</a>.</span>
</li>
<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe</span> <a href="Link 1" rel="">Text 2</a>.<span style="font-family:arial, helvetica, sans-serif;"> </span>
</li>
<li>
Siehe <a href="Link 1" rel="">Text 3</a>.
</li>
And here comes the necessary javascript code for my problems. First, I delete every span element. After that I want to replace the "a href" parts and increase the number of the new string.
var neu = document.getElementById("ausgabe").value;
var nummer = 0;
function getNextDlcNumber() {
return ++nummer;
}
var ersetzen = neu
.replace(/<span.*?>(.*?)<\/span>/g, "$1") // Gets rid of every span
.replace(/\s<li>\n\s\sSiehe\s*<a href=".*?" rel="">(.*?)<\/a>\.\n\s<\/li>/g, "\t<li>\n\t\tSiehe <a class=\"trophiesAnkerLink\" href=\"#dlc" + getNextDlcNumber() + "\" rel=\"\">$1</a>.\n\t</li>")); // Replaces a href with increasing dlc numbers
document.getElementById("ausgabe").value = ersetzen;
There are two problems with this:
-
The first and third "a href" are replaced successfully. But the second one isn't and I can't figure out why. I think it has something to do with the span tag between "Siehe" and the start of the "a" tag, however the span should get deleted due to the first replace so I'm not sure if that's what causes the problem. I tried using "Siehe\s*<a", "Siehe <a" as well as an or using | that contained the "
</span>
" but none of that worked. -
The number after "#dlc" isn't increasing, it just stays at "#dlc1" even for the third one. Do I need to do that in a different way?
Here's the output after using the js:
<li>
Siehe <a class="trophiesAnkerLink" href="#dlc1" rel="">Text 1</a>.
</li>
<li>
Siehe <a href="Link 1" rel="">Text 2</a>.
</li>
<li>
Siehe <a class="trophiesAnkerLink" href="#dlc1" rel="">Text 3</a>.
</li>
I hope I posted every necessary information. If not, I can provide more. Thanks for your help in advance
答案1
得分: 2
以下是翻译好的内容:
实际上,手动解析和编辑DOM元素内容是一个非常不好的主意,你不必让生活变得复杂并重新发明轮子。
您可以使用JavaScript内置方法直接访问链接元素的.href
属性,并直接更改它,甚至不使用.replace()
方法。
这是您的代码示例:
let elements = Array.from(document.getElementById("ausgabe").querySelectorAll("a"));
elements.forEach(a => a.href = "#dlc" + getNextDlcNumber());
您可以看到,这可以只是一行代码,实现您试图达到的一切目标。
演示:
<div id="ausgabe">
<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe <a href="Link 1" rel="">Text 1</a>.</span>
</li>
<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe</span> <a href="Link 1" rel="">Text 2</a><span style="font-family:arial, helvetica, sans-serif;"> </span>
</li>
<li>
Siehe <a href="Link 1" rel="">Text 3</a>.
</li>
</div>
当悬停在链接上时,您可以检查links
的新值,et voilà。
英文:
Actually it's a very bad idea to manually parse and edit DOM elements contents, you don't have to complicate your life and reinvent the wheel.
You can use JS built-in methods to directly access .href
attribute of your link elements and change it directly, without even using .replace()
method.
This is how can be your code:
let elements = Array.from(document.getElementById("ausgabe").querySelectorAll("a"))
elements.forEach(a => a.href = "#dlc" + getNextDlcNumber());
You can see it can just be a one liner code, to do all what you were trying to achieve.
Demo:
<!-- begin snippet: js hide: true console: true babel: false -->
<!-- language: lang-js -->
var nummer = 0;
function getNextDlcNumber() {
return ++nummer;
}
Array.from(document.getElementById("ausgabe").querySelectorAll("a")).forEach(a => a.href = "#dlc" + getNextDlcNumber());
<!-- language: lang-html -->
<div id="ausgabe">
<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe <a href="Link 1" rel="">Text 1</a>.</span>
</li>
<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe</span> <a href="Link 1" rel="">Text 2</a>.<span style="font-family:arial, helvetica, sans-serif;"> </span>
</li>
<li>
Siehe <a href="Link 1" rel="">Text 3</a>.
</li>
</div>
<!-- end snippet -->
You can check the new values of your links
by hovering them, et voilà.
答案2
得分: 1
代码部分不需要翻译,以下是代码之外的内容的中文翻译:
如其他人在评论和回答中所述,使用DOM来解析textarea
中的值更容易生成所需的输出。以下是两个版本(DOM解析和文本解析),以便您可以比较使用DOM解析与文本解析的简便性。
(这两个代码版本都可以重写和精简。它们写得详细是为了更容易调试样本。)
DOM解析版本:
<textarea id="ausgabe" rows="10" cols="50"></textarea>
<textarea id="ausgabe-result" rows="10" cols="50"></textarea>
<div>
<button id="parse-textarea-dom">DOM解析</button>
</div>
<ul id="ausgabe-list-dom"></ul>
文本解析版本,生成相同的输出:
<textarea id="ausgabe" rows="10" cols="50"></textarea>
<textarea id="ausgabe-result" rows="10" cols="50"></textarea>
<div>
<button id="parse-textarea-text">文本解析</button>
</div>
<ul id="ausgabe-list-text"></ul>
请注意,这些代码中包含了HTML和JavaScript的示例,用于演示DOM解析和文本解析的不同方法。
英文:
As others have stated in comments and answers, using the DOM to parse the value in the textarea
is much easier to generate the output you want. Below are two versions (DOM and text parsing) so that you can compare the simplicity of using DOM parsing versus text parsing.
(Both code versions can be rewritten and condensed. They are verbose to make the samples easier to debug.)
DOM parsing version:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
document.querySelector("#parse-textarea-dom").addEventListener("click", parseDom);
const inputHtml = `<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe <a href="Link 1" rel="">Text 1</a>.</span>
</li>
<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe</span> <a href="Link 1" rel="">Text 2</a>.<span style="font-family:arial, helvetica, sans-serif;"> </span>
</li>
<li>
Siehe <a href="Link 1" rel="">Text 3</a>.
</li>`;
document.querySelector("#ausgabe").textContent = inputHtml;
let number = 0;
function getNextDlcNumber() {
return ++number;
}
function parseDom() {
number = 0;
const neu = document.getElementById("ausgabe").value;
const ulElem = document.createElement("ul");
ulElem.innerHTML = neu;
ulElem.querySelectorAll("li").forEach(liElem => {
getNextDlcNumber();
const anchElem = liElem.querySelector("a");
anchElem.href = `#dlc${number}`;
anchElem.className = "trophiesAnkerLink";
liElem.removeChild(liElem.firstElementChild);
liElem.textContent = "Siehe ";
liElem.appendChild(anchElem);
});
document.getElementById("ausgabe-list-dom").appendChild(ulElem);
document.getElementById("ausgabe-list-dom").scrollIntoView();
document.getElementById("ausgabe-result").value = ulElem.innerHTML;
}
<!-- language: lang-html -->
<textarea id="ausgabe" rows="10" cols="50"></textarea>
<textarea id="ausgabe-result" rows="10" cols="50"></textarea>
<div>
<button id="parse-textarea-dom">DOM Parse</button>
</div>
<ul id="ausgabe-list-dom"></ul>
<!-- end snippet -->
The text parsing version for the same output:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
document.querySelector("#parse-textarea-text").addEventListener("click", parseText);
const inputHtml = `<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe <a href="Link 1" rel="">Text 1</a>.</span>
</li>
<li>
<span style="font-family:arial, helvetica, sans-serif;">Siehe</span> <a href="Link 1" rel="">Text 2</a>.<span style="font-family:arial, helvetica, sans-serif;"> </span>
</li>
<li>
Siehe <a href="Link 1" rel="">Text 3</a>.
</li>`;
document.querySelector("#ausgabe").textContent = inputHtml;
// stackoverflow.com/questions/31412765/regex-to-remove-white-spaces-blank-lines-and-final-line-break-in-javascript
function condenseHTML(html) {
return html.split('\n')
.map(s => {
return s.replace(/^\s*|\s*$/g, "");
})
.filter(x => {
return x;
})
.join("");
}
function getStringBetween(str, start, end) {
const result = str.match(new RegExp(start + "(.*)" + end));
return Array.isArray(result) && result.length > 1 ? result[1] : "";
}
let number = 0;
function getNextDlcNumber() {
return ++number;
}
function parseText() {
number = 0;
const neu = document.getElementById("ausgabe").value;
const condensed = condenseHTML(neu);
// Remove every <span> element
const spanRemoved = condensed.replace(/<span.*?>(.*?)<\/span>/g, "$1");
const pattern = /<li>(.*?)<\/li>/gi;
const ersetzen = spanRemoved.replace(pattern, (li) => {
getNextDlcNumber();
const anchor = li.match(/<a href=".*?" rel="">(.*?)<\/a>/gs);
const anchorText = Array.isArray(anchor) ?
getStringBetween(anchor[0], '\>', '\<') : "";
const replaceStr = `<li>
Siehe <a class="trophiesAnkerLink" href="#dlc${number}" rel="">${anchorText}</a>.
</li>`;
return replaceStr + "\n";
});
document.getElementById("ausgabe-list-text").innerHTML = ersetzen;
document.getElementById("ausgabe-list-text").scrollIntoView();
document.getElementById("ausgabe-result").value = ersetzen;
}
<!-- language: lang-html -->
<textarea id="ausgabe" rows="10" cols="50"></textarea>
<textarea id="ausgabe-result" rows="10" cols="50"></textarea>
<div>
<button id="parse-textarea-text">Text Parse</button>
</div>
<ul id="ausgabe-list-text"></ul>
<!-- end snippet -->
答案3
得分: 0
尝试使用 neu.replaceAll(pattern, replacement)
。
文档链接: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
英文:
Try using neu.replaceAll(pattern, replacement)
.
Doc: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论