it-swarm-vi.com

Làm cách nào để tập tin khác bỏ qua các bình luận (dòng bắt đầu bằng #)?

Tôi có hai tệp cấu hình, bản gốc từ trình quản lý gói và một tệp tùy chỉnh được tự sửa đổi. Tôi đã thêm một số ý kiến ​​để mô tả hành vi.

Làm cách nào tôi có thể chạy diff trên các tệp cấu hình, bỏ qua các nhận xét? Một dòng nhận xét được xác định bởi:

  • khoảng trắng hàng đầu tùy chọn (tab và dấu cách)
  • dấu băm (#)
  • bất cứ nhân vật nào khác

Biểu thức chính quy (đơn giản nhất) bỏ qua yêu cầu đầu tiên sẽ là #.*. Tôi đã thử --ignore-matching-lines=RE (-I RE) tùy chọn GNU diff 3.0, nhưng tôi không thể làm cho nó hoạt động với RE đó. Tôi cũng đã thử .*#.*.*\#.* không có may mắn. Nghĩa đen là đặt dòng (Port 631) vì RE không khớp với bất cứ điều gì, cũng không giúp đặt RE giữa các dấu gạch chéo.

Như được đề xuất trong hương vị regex của công cụ khác có vẻ thiếu? , tôi đã thử grep -G:

grep -G '#.*' file

Điều này có vẻ phù hợp với các ý kiến, nhưng nó không hoạt động cho diff -I '#.*' file1 file2.

Vì vậy, nên sử dụng tùy chọn này như thế nào? Làm cách nào tôi có thể thực hiện diff bỏ qua một số dòng nhất định (trong trường hợp của tôi, nhận xét)? Vui lòng không đề xuất greping tệp và so sánh các tệp tạm thời.

56
Lekensteyn

Theo Gilles, tùy chọn -I Chỉ bỏ qua một dòng nếu không có gì khác trong tập hợp đó ngoại trừ kết quả khớp -I. Tôi đã không hoàn toàn nhận được nó cho đến khi tôi thử nghiệm nó.

Các bài kiểm tra

Ba tập tin có liên quan đến thử nghiệm của tôi:
[.__.] Tệp test1:

    text

Tệp test2:

    text
    #comment

Tệp test3:

    changed text
    #comment

Các lệnh:

$ # comparing files with comment-only changes
$ diff -u -I '#.*' test{1,2}
$ # comparing files with both comment and regular changes
$ diff -u -I '#.*' test{2,3}
--- test2       2011-07-20 16:38:59.717701430 +0200
+++ test3       2011-07-20 16:39:10.187701435 +0200
@@ -1,2 +1,2 @@
-text
+changed text
 #comment

Cách khác

Vì cho đến nay vẫn chưa có câu trả lời giải thích cách sử dụng tùy chọn -I, Tôi sẽ cung cấp một giải pháp thay thế hoạt động trong bash shell:

diff -u -B <(grep -vE '^\s*(#|$)' test1)  <(grep -vE '^\s*(#|$)' test2)
  • diff -u - khác biệt thống nhất [.__.]
    • -B - bỏ qua các dòng trống
  • <(command) - một tính năng bash được gọi là thay thế quá trình mở ra một mô tả tệp cho lệnh, điều này loại bỏ sự cần thiết của một tệp tạm thời
  • grep - lệnh in các dòng (không) khớp với mẫu [.__.]
    • -v - hiển thị các dòng không khớp
    • E - sử dụng các biểu thức chính quy mở rộng
    • '^\s*(#|$)' - một biểu thức chính quy khớp với các bình luận và các dòng trống [.__.]
      • ^ - khớp với phần đầu của một dòng
      • \s* - khớp với khoảng trắng (tab và dấu cách) nếu có
      • (#|$) Khớp với dấu băm hoặc cách khác là kết thúc một dòng
54
Lekensteyn

Thử:

diff -b -I '^#' -I '^ #' file1 file2

Xin lưu ý rằng regex phải khớp với dòng tương ứng trong cả hai tệp và nó khớp với mọi dòng thay đổi trong hunk để hoạt động, nếu không nó vẫn sẽ hiển thị sự khác biệt.

Sử dụng dấu ngoặc đơn để bảo vệ mẫu khỏi mở rộng Shell và để thoát các ký tự dành riêng cho biểu thức chính quy (ví dụ: ngoặc).

Chúng ta có thể đọc trong diffutils thủ công:

Tuy nhiên, -I chỉ bỏ qua việc chèn hoặc xóa các dòng có chứa biểu thức chính quy nếu mọi dòng thay đổi trong hunk (mọi phần chèn và mọi phần xóa) khớp với biểu thức chính quy.

Nói cách khác, đối với mỗi thay đổi không thể bỏ qua, diff sẽ in toàn bộ các thay đổi trong vùng lân cận, bao gồm cả những thay đổi không thể biết được. Bạn có thể chỉ định nhiều hơn một biểu thức chính quy cho các dòng bỏ qua bằng cách sử dụng nhiều hơn một -I Lựa chọn. diff cố gắng khớp từng dòng với từng biểu thức chính quy, bắt đầu với biểu thức cuối cùng được đưa ra.

Hành vi này cũng được giải thích tốt bởi armel here .

Liên quan: Làm cách nào tôi có thể thực hiện tìm khác biệt mà bỏ qua tất cả các nhận xét?

7
kenorb

Sau khi tìm kiếm trên web, cách khác của Lekensteyn là cách tốt hơn tôi tìm thấy.

Nhưng tôi muốn sử dụng đầu ra khác nhau như một bản vá ... và có một vấn đề vì số dòng được lưu giữ vì "grep -v".

Vì vậy, tôi có mục đích cải thiện dòng lệnh này:

diff -u -B <(sed 's/^[[:blank:]]*#.*$/ /' file1)  <(sed 's/^[[:blank:]]*#.*$/ /' file2)

Nó không hoàn hảo nhưng số dòng được giữ trong tệp vá.

Tuy nhiên, nếu một dòng mới được thêm vào thay vì dòng bình luận ... bình luận sẽ được tạo ra Hunk FAILED khi vá như chúng ta có thể thấy dưới đây.

File test1:
  text
  #comment
  other text
File test2:
  text
  new line here
  #comment changed
  other text changed

kiểm tra ngay lệnh của chúng tôi

$ echo -e "#!/usr/bin/sed -f\ns/^[[:blank:]]*#.*$/ /" > outcom.sed
$ echo "diff -u -B <(./outcom.sed \$1)  <(./outcom.sed \$2)" > mydiff.sh
$ chmod +x mydiff.sh outcom.sed
$ ./mydiff.sh file1 file2 > file.dif
$ cat file.dif
--- /dev/fd/63  2014-08-23 10:05:08.000000000 +0200
+++ /dev/fd/62  2014-08-23 10:05:08.000000000 +0200
@@ -1,2 +1,3 @@
 text
+new line

-other text
+other text changed

/ dev/fd/62 &/dev/fd/63 là tệp được tạo bởi quá trình thay thế. Dòng giữa "+ dòng mới" và "văn bản khác" là ký tự không gian mặc định được xác định trong biểu thức sed của chúng tôi để thay thế các nhận xét.

Và bây giờ, những gì đang đến khi chúng tôi áp dụng bản vá này:

$ patch -p0 file1 < file.dif 
patching file file1
Hunk #1 FAILED at 1.
1 out of 1 hunk FAILED -- saving rejects to file file1.rej

Giải pháp là không sử dụng định dạng diff hợp nhất mà không có -u

$ echo "diff -B <(./outcom.sed \$1)  <(./outcom.sed \$2)" > mydiff.sh
$ ./mydiff.sh file1 file2 > file.dif
$ cat file.dif
1a2
> new line
3c4
< other text
---
> other text changed
$ patch -p0 file1 < file.dif 
patching file file1
$ cat file1
text
new line
#comment
other text changed

bây giờ vá tập tin làm việc tập tin (không có bảo hành kết quả trong quá trình khác biệt rất phức tạp).

3
syjust

Tôi thường bỏ qua sự lộn xộn này bởi một trong hai:

  • Tạo các phiên bản không nhận xét bằng cách sử dụng grep -v "^#" | cat -s và phân biệt chúng hoặc ...
  • Sử dụng vim -d để xem các tập tin. Cú pháp tô sáng quan tâm đến việc đưa ra nhận xét so với sự khác biệt không bình luận khá rõ ràng. Điểm nổi bật khác biệt của sự khác biệt trong dòng để bạn có thể thấy những giá trị hoặc phần nào của các giá trị đã được thay đổi trong nháy mắt làm cho điều này trở thành yêu thích của tôi.
1
Caleb

Đây là những gì tôi sử dụng để xóa tất cả các dòng nhận xét - cả những dòng bắt đầu bằng một tab hoặc dấu cách - và các dòng trống:

egrep -v "^$|^[[:space:]]*#" /path/to/file

hoặc bạn có thể làm

sed -e '/^#.*/d' -e 's/#.*//g' | cat -s
0
Philomath