Python thay thế toàn bộ dòng trong tệp

Khi thao tác với tệp văn bản, một số chương trình đọc cả một dòng vào bộ nhớ. Nếu tệp đầu vào có dòng quá lớn, chương trình có thể bị lỗi nếu không đủ bộ nhớ để lưu dòng

Trong hướng dẫn này, chúng ta sẽ xem cách chúng ta có thể thay thế một chuỗi trong tệp văn bản một dòng rất lớn. Ví dụ: chúng tôi có thể muốn thao tác với tệp 50 GB chỉ chứa một dòng văn bản. Vì một số chương trình không thể xử lý các tệp văn bản một dòng rất lớn, chúng tôi sẽ xem chúng tôi có những lựa chọn thay thế nào

2. Tập tin mục tiêu

Một số thư viện JavaScript hiện đại nén tất cả mã thành một dòng. Giả sử chúng ta có một tệp JavaScript một dòng có tên original. js với một lỗi đánh máy trong đó. Nó gọi phương thức “bộ lọc” thay vì “bộ lọc“. Chúng tôi sẽ sửa lỗi đánh máy này trong các phần sau

3. Sử dụng tr và sed

Chúng ta có thể sử dụng tr và sed để thay thế dòng. Đây sẽ là quy trình gồm 2 bước để tách dòng và thay thế chuỗi

3. 1. Chia đôi hàng dài

Chúng tôi thường sử dụng sed để thay thế một chuỗi, nhưng sed sẽ cố gắng tải toàn bộ dòng vào bộ nhớ. Để khắc phục điều này, chúng tôi sẽ chia dòng thành nhiều dòng nhỏ hơn. Sau đó, chúng tôi sẽ cung cấp sed với đầu vào mới này để thay thế chuỗi. Cuối cùng, chúng ta sẽ nối lại đầu ra thành một dòng

Trong Linux, theo mặc định, các dòng được phân tách bằng ký tự xuống dòng “\n”. Trong trường hợp của chúng tôi, chúng tôi sẽ thay thế một ký tự khác bằng “\n” và nạp sed bằng đầu vào mới này. Ta phải chọn một ký tự không có trong chuỗi muốn thay thế. Ngoài ra, tệp đầu vào phải chứa ký tự và tạo ra các dòng tương đối nhỏ khi chúng ta thay thế nó bằng “\n”

Để chia một dòng thành nhiều dòng, chúng ta có thể sử dụng chương trình tr để thay thế một ký tự bằng “\n”. tr xử lý từng ký tự một, nghĩa là nó có thể xử lý các tệp lớn với các dòng lớn mà không gặp sự cố

tr nhận hai tham số. Nó sẽ thay thế tham số đầu tiên bằng tham số thứ hai. Hãy xem cách thay thế “;”

$ echo "line one;line two" | tr ";" "\n"
line one
line two

Trong trường hợp có dòng mới trong tệp của chúng tôi, chúng tôi nên thay đổi cả hai “;” . Làm điều này sẽ giúp giữ nguyên các ký tự dòng mới ban đầu. Để làm điều này, chúng tôi sẽ chạy tr “;\n” “\n;”. Bằng cách này, tr sẽ thay đổi ký tự đầu tiên từ tham số thứ nhất [;] bằng ký tự đầu tiên từ tham số thứ hai [\n] và cả ký tự thứ hai từ tham số thứ nhất [\n] bằng ký tự thứ hai từ tham số thứ hai

Khi chúng tôi thêm các dòng mới vào đầu vào, sau đó chúng tôi sẽ nối lại các dòng để đầu ra nhất quán với đầu vào. Điều này có thể dễ dàng thực hiện bằng cách hoán đổi các tham số tr để tạo ra sự thay thế nghịch đảo. Hãy sử dụng tr “;\n” “\n;”

$ echo "line one;line two" | tr ";\n" "\n;" | tr "\n;" ";\n"
line one;line two

Chúng ta có thể thấy, chúng ta đã sản xuất cùng một đầu vào

3. 2. Thay thế chuỗi

Sau khi chia đầu vào thành nhiều dòng, chúng ta có thể chạy sed để thay thế chuỗi. Hãy xem cách chạy sed để thay thế chuỗi “Alan Turing” bằng “Alan Mathison Turing”

$ echo "Alan Turing was born in London." | sed 's/Alan Turing/Alan Mathison Turing/'
Alan Mathison Turing was born in London.

Cho đến giờ, chúng ta đã biết cách tách các dòng dài, thay thế một chuỗi và nối lại các dòng. Cuối cùng, chúng ta có thể viết tập lệnh để thay thế một chuỗi trong một tệp có dòng rất dài

Nếu chúng ta muốn thay thế “. bộ lọc[” với “. filter[” trong tệp mục tiêu của chúng ta, chúng ta có thể chọn ký tự “;” để chia dòng. Các ";" . filter[” string, và nó là một ký tự thường xuất hiện trong tệp JavaScript, do đó, nó sẽ tạo ra các dòng ngắn. Hãy xem cách sửa lỗi gốc. js và ghi kết quả vào fixed. js

$ tr ";\n" "\n;" < original.js | sed 's/\.fliter[/.filter[/' | tr "\n;" ";\n" > fixed.js

Lưu ý rằng chúng ta phải thoát ký tự dấu chấm khi chúng ta thay thế “. bộ lọc[” với “. lọc[". Điều này là do lệnh thay thế của sed nhận một biểu thức chính quy cho tham số đầu tiên

4. sử dụng awk

Có những chương trình khác có thể thay thế một chuỗi trong tệp văn bản. Thay vì sed, chúng ta có thể sử dụng awk và hàm gsub của nó. Đây sẽ là quy trình gồm 2 bước để định cấu hình dấu phân cách dòng của awk và thay thế chuỗi

4. 1. Thay đổi dấu phân cách dòng

Với awk, chúng ta có thể thay đổi ký tự dùng để phân định dòng. Sau đó, thay vì sử dụng dấu phân cách dòng “\n” mặc định, chúng ta có thể sử dụng một ký tự khác để tạo ra các dòng nhỏ hơn. Như chúng ta đã thấy trong phần trước, chúng ta phải chọn một ký tự không có trong chuỗi mà chúng ta muốn thay thế

Để thay đổi dấu phân cách dòng được sử dụng trong awk, chúng tôi sẽ đặt biến RS thành ký tự mong muốn bên trong khối BEGIN. Chẳng hạn, nếu chúng ta chọn “;” . Hãy xem nó hoạt động như thế nào

$ echo "line one;line two" | awk 'BEGIN{RS=";"}{print}'
line one
line two

Như đã đề cập ở phần trước, chúng ta phải tạo ra đầu ra phù hợp với đầu vào. Ngay cả khi awk tách dòng với dấu “;” . Chúng ta có thể thấy rằng chức năng in của awk viết một dòng mới không có trong đầu vào ban đầu

Thay vào đó, hãy sử dụng hàm printf để không có dòng mới nào được thêm vào

$ echo "line one;line two" | awk 'BEGIN{RS=";"}{printf "%s", $0}'
line oneline two

Chúng ta có thể thấy, chúng ta chỉ thiếu dấu “;” . Chúng tôi biết rằng tất cả các dòng bắt đầu bằng dấu phân cách dòng, ngoại trừ dòng đầu tiên. Vì vậy, hãy thêm dấu “;” vào trước

$ echo "line one;line two" | awk 'BEGIN{RS=";"}{
    if [NR != 1] {
        printf "%c", RS
    }
    printf "%s", $0
}'
line one;line two

Lưu ý rằng chúng tôi đã sử dụng biến NR để lấy số dòng hiện tại và bỏ qua dòng đầu tiên. Ngoài ra, chúng tôi đã sử dụng biến RS để in dấu phân cách dòng

4. 2. Thay thế chuỗi

Chúng ta đã xem cách sử dụng awk để xử lý tệp chia dòng với bất kỳ ký tự nào khác ngoài “\n“. Vì vậy, bây giờ chúng ta có thể thay thế một chuỗi trong một tệp có dòng rất dài

Để thay thế một chuỗi bằng awk, chúng ta sẽ sử dụng hàm gsub. Chức năng này hoạt động tương tự như lệnh thay thế của sed. Nó lấy tham số đầu tiên làm biểu thức chính quy và thay thế nó bằng tham số thứ hai. Sau đó, chúng tôi sẽ gọi gsub để thay thế và sau đó sử dụng mã từ ví dụ trước để in dòng

Chúng tôi sẽ lặp lại ý tưởng tương tự từ phần trước. Hãy sửa tệp mục tiêu của chúng ta bằng cách thay thế “. bộ lọc[” với “. lọc["

$ awk 'BEGIN{RS=";"} {
    gsub["\\.fliter\\[", ".filter["]
    if [NR != 1] {
        printf "%c", RS
    }
    printf "%s", $0
}' < original.js > fixed.js

Lưu ý rằng có một sự khác biệt với sed khi chúng ta thoát khỏi các ký tự. Chúng ta cũng phải thoát khỏi ký tự “[” và chúng ta phải sử dụng dấu gạch chéo ngược kép

5. Phần kết luận

Trong hướng dẫn này, chúng ta đã thấy hai phương pháp để thay thế một chuỗi bên trong tệp một dòng rất lớn

Một mặt, chúng tôi đã thấy cách sử dụng sed. Trong trường hợp này, chúng tôi phải sử dụng tr để chia tệp một dòng thành nhiều dòng. Mặt khác, chúng tôi đã thấy rằng chúng tôi cũng có thể sử dụng awk bằng cách đặt biến RS bằng một ký tự sẽ phân chia dòng

tác giả dưới cùng

Nếu bạn có một vài năm kinh nghiệm trong hệ sinh thái Linux và bạn muốn chia sẻ trải nghiệm đó với cộng đồng, hãy xem Nguyên tắc đóng góp của chúng tôi

Chủ Đề