web-dev-qa-db-ja.com

コメントを無視してファイルを比較する方法(#で始まる行)?

パッケージマネージャーからの元の構成ファイルと、自分で変更したカスタマイズされたものの2つの構成ファイルがあります。動作を説明するコメントを追加しました。

コメントをスキップして、構成ファイルでdiffを実行するにはどうすればよいですか?コメント行は次のように定義されます。

  • オプションの先行空白(タブとスペース)
  • ハッシュ記号(#
  • 他の何か

最初の要件をスキップする(最も単純な)正規表現は#.*--ignore-matching-lines=RE-I RE)GNU diff 3.0のオプションですが、そのREで動作させることができませんでした。.*#.*および.*\#.*運がなければ。文字通り行(Port 631REは何にも一致しないため、スラッシュの間にREを置くこともできません。

「diff」ツールの正規表現のフレーバーが不足しているように見えますか? で提案されているように、私はgrep -G

grep -G '#.*' file

これはコメントと一致するようですが、diff -I '#.*' file1 file2

では、このオプションはどのように使用すべきですか?特定の行(私の場合はコメント)をdiffスキップするにはどうすればよいですか?ファイルをgrepingして一時ファイルを比較しないでください。

56
Lekensteyn

Gilles氏によれば、_-I_オプションは、そのセット内で_-I_の一致を除いて何も一致しない場合にのみ行を無視します。テストするまで完全には手に入れませんでした。

テスト

テストには3つのファイルが関係しています。
ファイル_test1_

_    text
_

ファイル_test2_

_    text
    #comment
_

ファイル_test3_

_    changed text
    #comment
_

コマンド:

_$ # 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
_

代替方法

これまでに_-I_オプションを正しく使用する方法を説明する答えはないため、bashシェルで機能する代替手段を提供します。

_diff -u -B <(grep -vE '^\s*(#|$)' test1)  <(grep -vE '^\s*(#|$)' test2)
_
  • _diff -u_-統一されたdiff
    • _-B_-空白行を無視
  • <(command)-コマンドのファイル記述子を開く プロセス置換 と呼ばれるbash機能。これにより、一時ファイルが不要になります。
  • grep-パターンに一致する(ではない)行を印刷するためのコマンド
    • _-v_-一致しない行を表示
    • E-拡張正規表現を使用
    • '^\s*(#|$)'-コメントと空の行に一致する正規表現
      • _^_-行頭に一致
      • _\s*_-空白(タブとスペース)があれば一致します
      • _(#|$)_ハッシュマーク、または行末に一致
54
Lekensteyn

試してください:

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

正規表現は両方のファイルの対応する行と一致する必要があり、機能するためには、ハンク内の変更されたすべての行と一致する必要があります。一致しない場合でも、違いが表示されます。

シェルの展開からパターンを保護し、正規表現で予約されている文字(たとえば、ブラケット)をエスケープするには、一重引用符を使用します。

diffutils マニュアルで読むことができます:

ただし、-Iは、ハンク内の変更されたすべての行(すべての挿入とすべての削除)が正規表現と一致する場合にのみ、正規表現を含む行の挿入または削除を無視します。

言い換えると、無視できない変更ごとに、diffは無視できる変更を含む、その付近の変更の完全なセットを出力します。複数の-Iオプションを使用して、無視する行に複数の正規表現を指定できます。 diffは、指定された最後の行から始めて、各行を各正規表現と照合しようとします。

この動作は armel here でもよく説明されています。

関連: すべてのコメントを無視するdiffを実行するにはどうすればよいですか?

7
kenorb

Webで検索した後、Lekensteynの代替方法が私が見つけたより良いものです。

しかし、dif出力をパッチとして使用したいのですが、 "grep -v"のために行番号がメモに保持されるため問題があります。

だから私はこのコマンドラインを改善することを目的としています:

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

完璧ではありませんが、行番号はパッチファイルに保持されます。

ただし、コメント行の代わりに新しい行が追加された場合...次のように、パッチング時にコメントがHunk FAILEDを生成します。

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

コマンドを今テストしてください

$ 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は、プロセス置換によって生成されるファイルです。 「+ new line」と「-other text」の間の行は、コメントを置き換えるためにsed式で定義されているデフォルトの空白文字です。

そして、このパッチを適用するとどうなるでしょうか。

$ 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

解決策は、-uなしで統合diff形式を使用しないことです

$ 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

現在、パッチファイルの作業ファイル(非常に複雑なdiffプロセスの結果の保証なし)。

3
syjust

私は通常、次のいずれかによってこの混乱を無視します。

  • grep -v "^#" | cat -sを使用してコメント化されていないバージョンを生成し、それらを比較するか...
  • vim -dを使用してファイルを確認します。構文の強調表示により、コメントと非コメントの違いが明確になります。一目で変更された値または値の一部が一目でわかるように、インラインの違いを強調表示することで、これが私のお気に入りです。
1
Caleb

ここに私がすべてのコメント行(タブまたはスペースで始まる行も含む)と空白行を削除するために使用するものがあります。

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

またはあなたができる

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