Làm thế nào để chỉ thay thế các nhóm bị bắt?


193

Tôi có mã HTML trước và sau chuỗi:

name="some_text_0_some_text"

Tôi muốn thay thế 0 bằng một cái gì đó như:!NEW_ID!

Vì vậy, tôi đã thực hiện một regex đơn giản:

.*name="\w+(\d+)\w+".*

Nhưng tôi không thấy làm thế nào để thay thế độc quyền khối bị bắt.

Có cách nào để thay thế một kết quả đã chụp như ($ 1) bằng một chuỗi khác không?

Kết quả sẽ là:

name="some_text_!NEW_ID!_some_text"

Câu trả lời:


358

Một giải pháp là thêm hình ảnh chụp cho văn bản trước và sau:

str.replace(/(.*name="\w+)(\d+)(\w+".*)/, "$1!NEW_ID!$3")

76
Chúc mừng từ tương lai! Giải pháp của bạn trông thực sự gọn gàng. Bạn có thể vui lòng giải thích câu trả lời của bạn?
Polyducks

21
Dấu ngoặc đơn được sử dụng để tạo "nhóm", sau đó được gán chỉ số cơ sở 1, có thể truy cập thay thế bằng a $, vì vậy từ đầu tiên (\w+)nằm trong một nhóm và trở thành $1, phần giữa (\d+)là nhóm thứ hai, nhưng được bỏ qua trong thay thế), và nhóm thứ ba là $3. Vì vậy, khi bạn đưa ra chuỗi thay thế "$1!new_ID!$3", $ 1 và $ 3 được thay thế tự động bằng nhóm thứ nhất và nhóm thứ ba, cho phép nhóm thứ 2 được thay thế bằng chuỗi mới, duy trì văn bản xung quanh nó.
mix3d

4
Điều đó đang được nói, trong khi tôi hiểu nó hoạt động như thế nào, tôi đã hy vọng cho một giải pháp thanh lịch hơn>. <Tuy nhiên, tôi có thể tiến lên với mã của mình ngay bây giờ!
mix3d

9
1) Bạn thậm chí không cần phải chụp \ d + 2) Tại sao bạn nói nó không thanh lịch? Chụp là để giữ đồ đạc, không vứt nó đi. Những gì bạn muốn giữ là AROUND \ d +, vì vậy nó thực sự có ý nghĩa (và đủ thanh lịch) để chụp những phần xung quanh này.
Sir4ur0n

3
Giải pháp tốt đẹp. Điều gì sẽ xảy ra nếu chúng ta muốn thay thế các nhóm chụp bằng cách sử dụng nhóm chụp làm cơ sở cho việc chuyển đổi? Có một giải pháp thanh lịch không kém để làm điều này? Hiện tại tôi lưu trữ các nhóm bị bắt trong một danh sách, lặp chúng và thay thế nhóm bắt giữ bằng giá trị được chuyển đổi ở mỗi lần lặp
sookie

15

Giờ đây, Javascript đã có giao diện (kể từ ES2018 ), trên các môi trường mới hơn, bạn có thể tránh các nhóm hoàn toàn trong các tình huống như thế này. Thay vào đó, lookbehind cho những gì đứng trước nhóm bạn đã chụp, và lookahead cho đến sau, và thay thế bằng chỉ !NEW_ID! :

const str = 'name="some_text_0_some_text"';
console.log(
  str.replace(/(?<=name="\w+)\d+(?=\w+")/, '!NEW_ID!')
);

Với phương pháp này, trận đấu đầy đủ chỉ là phần cần được thay thế.

  • (?<=name="\w+)- Lookbehind cho name", theo sau là các ký tự từ (may mắn thay, lookbehind không phải là chiều rộng cố định trong Javascript!)
  • \d+ - Ghép một hoặc nhiều chữ số - phần duy nhất của mẫu không nằm trong diện mạo, phần duy nhất của chuỗi sẽ nằm trong kết quả khớp
  • (?=\w+")- Nhìn cho các ký tự từ theo sau bởi " `

Hãy nhớ rằng lookbehind là khá mới. Nó hoạt động trong các phiên bản hiện đại của V8 (bao gồm Chrome, Opera và Node), nhưng không phải trong hầu hết các môi trường khác , ít nhất là chưa. Vì vậy, trong khi bạn có thể sử dụng lookbehind một cách đáng tin cậy trong Node và trong trình duyệt của riêng bạn (nếu nó chạy trên phiên bản V8 hiện đại), thì nó vẫn chưa được hỗ trợ đầy đủ bởi các máy khách ngẫu nhiên (như trên trang web công cộng).


Chỉ cần chạy thử nghiệm thời gian nhanh và khá ấn tượng về cách thức nhập liệu: jsfiddle.net/60neyop5
Kaiido

Nhưng nếu, ví dụ tôi muốn trích xuất số, bội số và "đặt lại", tôi cũng sẽ phải nhóm \d+, phải không?
Mosh Feu

@MoshFeu Sử dụng chức năng thay thế và sử dụng toàn bộ kết quả khớp, các chữ số: thay thế tham số thứ hai bằng match => match * 2. Các chữ số vẫn là toàn bộ khớp nhau, vì vậy không cần phải có nhóm
SurePerformance

Bắt được rồi. Cảm ơn!
Mosh Feu

2

Một cải tiến nhỏ cho câu trả lời của Matthew có thể là một cái nhìn thay vì nhóm bắt giữ cuối cùng:

.replace(/(\w+)(\d+)(?=\w+)/, "$1!NEW_ID!");

Hoặc bạn có thể chia theo số thập phân và tham gia với id mới của bạn như thế này:

.split(/\d+/).join("!NEW_ID!");

Ví dụ / Điểm chuẩn tại đây: https://codepen.io/jogai/full/oyNXBX


1

Với hai nhóm bắt giữ cũng có thể có được; Tôi cũng đã bao gồm hai dấu gạch ngang, như các ranh giới bên trái và bên phải bổ sung, trước và sau các chữ số, và biểu thức được sửa đổi sẽ trông giống như:

(.*name=".+_)\d+(_[^"]+".*)

const regex = /(.*name=".+_)\d+(_[^"]+".*)/g;
const str = `some_data_before name="some_text_0_some_text" and then some_data after`;
const subst = `$1!NEW_ID!$2`;
const result = str.replace(regex, subst);
console.log(result);


Nếu bạn muốn khám phá / đơn giản hóa / sửa đổi biểu thức, nó sẽ được giải thích trên bảng trên cùng bên phải của regex101.com . Nếu bạn muốn, bạn cũng có thể xem trong liên kết này , cách nó phù hợp với một số đầu vào mẫu.


Mạch RegEx

jex.im hình dung các biểu thức thông thường:

nhập mô tả hình ảnh ở đây


0

Một lựa chọn đơn giản hơn là chỉ chụp các chữ số và thay thế chúng.

const name = 'preceding_text_0_following_text';
const matcher = /(\d+)/;

// Replace with whatever you would like
const newName = name.replace(matcher, 'NEW_STUFF');
console.log("Full replace", newName);

// Perform work on the match and replace using a function
// In this case increment it using an arrow function
const incrementedName = name.replace(matcher, (match) => ++match);
console.log("Increment", incrementedName);

Tài nguyên

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.