2009-10-02 34 views
7

Tôi đã tìm thấy rất nhiều ví dụ để thay thế văn bản trong các tệp bằng regex. Tuy nhiên, tất cả đều có hai phiên bản:
1. Lặp lại tất cả các dòng trong tệp và áp dụng regex cho mỗi dòng đơn
2. Tải toàn bộ tệp.Tìm kiếm nhiều dòng regex trong toàn bộ tệp

No. 2 Không khả thi khi sử dụng tệp "của tôi" - chúng khoảng 2GiB ...
Đến số 1: Hiện tại đây là cách tiếp cận của tôi, tuy nhiên tôi tự hỏi ... Điều gì sẽ xảy ra nếu cần áp dụng một regex bao trùm nhiều hơn một dòng?

+1

Có thể tải dữ liệu này vào RDBMS không? –

+0

Tôi nghĩ bạn sẽ cần phải mô tả dữ liệu của bạn và regex tốt hơn để có được một đề xuất phong nha. –

+0

ok. Làm rõ ít: Thường thì tôi cần sửa đổi các tệp csv lớn. (ví dụ: chuyển đổi col 3 và 5) Tôi đã thấy rằng, sử dụng regex và sed, tôi có thể áp dụng các sửa đổi cần thiết thật nhanh. Tuy nhiên tôi "phát triển" và kiểm tra regex của tôi bằng cách sử dụng The Regulator, mà sẽ dẫn đến "clr-regex" mà sau đó phải được dịch thành cú pháp sed. Để tránh điều này tôi đã viết một công cụ nhỏ (C#), cho phép tôi áp dụng "clr-regex" vào một tập tin. NGAY BÂY GIỜ: Sử dụng công cụ này, bạn không thể áp dụng regex trải rộng trên nhiều dòng - vì tôi đang thực hiện phương pháp được đề cập ở trên không. 1. Câu hỏi trên có phần giả định. – Nils

Trả lời

2

Đây là Trả lời:
Không có cách nào dễ dàng

Tôi đã tìm thấy StreamRegex-Class để có thể thực hiện những gì tôi đang tìm kiếm.
Từ những gì tôi có thể nắm bắt của thuật toán:

  • Bắt đầu vào lúc bắt đầu của tập tin với một bộ đệm trống
  • làm (
    • thêm một đoạn của tập tin vào bộ đệm
    • nếu có sự trùng khớp trong bộ đệm
      • đánh dấu kết quả phù hợp
      • thả tất cả dữ liệu mà xuất hiện trước khi kết thúc trận đấu từ bộ đệm
  • ) trong khi vẫn có cái gì đó của tập tin trái

Bằng cách đó nó không phải là nessesary để tải toàn bộ tập tin - hoặc ít nhất là khả năng tải toàn bộ tập tin trong bộ nhớ bị giảm ...
Tuy nhiên: Trường hợp xấu nhất là không có kết quả khớp trong toàn bộ tệp - trong trường hợp này, toàn bộ tệp sẽ được tải vào bộ nhớ.

0

Có lẽ bạn có thể tải trong 2 dòng tại một thời điểm (hoặc nhiều hơn, tùy thuộc vào số lượng dòng bạn cho là phù hợp) và chồng chéo chúng, ví dụ: tải dòng 1-2, sau đó tải vòng tiếp theo dòng 2-3, tải tiếp theo 3-4; và thực hiện các regex trên nhiều dòng kết hợp, trong mỗi vòng lặp.

+0

Ý tưởng tốt, tuy nhiên mỗi dòng sẽ được regex'd có thể nhiều lần. Người ta sẽ phải xem xét các tác dụng phụ có thể xảy ra .. – Nils

+0

Hmm vâng, bạn nói đúng. Có lẽ chỉ phù hợp khi trận đấu bắt đầu trên hàng đầu tiên (trước khi bất kỳ trường hợp nào của ngắt dòng)? –

1

Regex không phải là cách để đi, đặc biệt là không phải với những lượng lớn văn bản này. Tạo một trình phân tích cú pháp nhỏ của riêng bạn:

  • đọc từng dòng tệp;
  • cho mỗi dòng:
    • vòng lặp thông qua dòng char bởi char giữ theo dõi của bất kỳ mở/đóng xâu
    • khi bạn gặp '/ *' (và bạn không 'bên' một chuỗi), cửa hàng mà bù đắp số lượng và vòng lặp cho đến khi bạn gặp đầu tiên '* /' và lưu trữ số đó cũng

Điều đó sẽ cung cấp cho bạn tất cả các starting- và numbe bế mạc-offset rs của các khối bình luận. Bây giờ bạn có thể thay thế chúng bằng cách tạo một tệp tạm thời và viết văn bản từ tệp gốc sang tệp tạm thời (và viết một thứ gì khác nếu bạn đang ở trong một khối nhận xét).

Chỉnh sửa: tệp nguồn của 2GiB ??

+0

Tôi có nói nguồn không? ;-) Không có dữ liệu "thô", thực tế là csv. – Nils

+0

Ah, tôi hiểu rồi. Không biết C#, nhưng sẽ tưởng tượng nó thậm chí sẽ không thể tạo ra các tệp nguồn lớn như vậy. –

0

Tôi muốn nói bạn nên phân tích trước/chuẩn hóa dữ liệu trước khi thực hiện các thay thế để mỗi dòng mô tả một tập hợp dữ liệu có thể cần phải áp dụng thay thế. Nếu không, bạn sẽ gặp phải các biến chứng với tính toàn vẹn dữ liệu mà không thể thực sự được giải quyết mà không có một loạt các khó khăn khác.

Nếu có cách tách dữ liệu thành các khối lôgíc thì bạn có thể xây dựng một chương trình sử dụng mẫu vẽ bản đồ để phân tích dữ liệu.

0

Tôi có Bart; bạn thực sự nên sử dụng một số loại phân tích cú pháp cho việc này.

Hoặc, nếu bạn không nhớ đẻ trứng một quá trình con, bạn có thể chỉ cần sử dụng sed (có một native port on windows, hoặc bạn có thể sử dụng Cygwin)

0

Nếu bạn không ngại bị bẩn đôi chút (và regex của bạn đủ đơn giản, hoặc có thể bạn muốn có tốc độ cao và không ngại một chút), bạn có thể sử dụng Ragel. Nó có thể nhắm mục tiêu C#, mặc dù trang web không đề cập đến nó. Bạn sẽ cần phải bọc một FileStream để cung cấp một bộ đệm chỉ mục hoặc sử dụng một tệp ánh xạ bộ nhớ (với các con trỏ không an toàn) trong một quá trình 64 bit để sử dụng điều này với các tệp lớn.

Các vấn đề liên quan