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

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

2つの設定ファイルがあります。 1つはパッケージマネージャのソース設定ファイル、もう1つは私が直接変更したカスタム設定ファイルです。動作を説明するためにいくつかの説明を追加しました。

diff設定ファイルをスキップするコメントを実行するには?コメント行は次のように定義されます。

  • オプションの先行スペース(タブとスペース)
  • ハッシュタグ( #)
  • その他の文字

最初の要件をスキップする(最も簡単な)正規表現はです。 GNU diff 3.0の()オプションを#.*試しましたが、対応するREでは機能しませんでした。私も試してみましたが、運がありませんでした。文字通り、行( )を何も一致しないものとして置き、スラッシュの間にREを入れることも役に立ちません。--ignore-matching-lines=RE-I RE.*#.*.*\#.*Port 631RE

提案通り「diff」ツールの正規表現スタイルが足りないと思いますか?、私は次のことを試しましたgrep -G

grep -G '#.*' file

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

それでは、このオプションをどのように使用する必要がありますか?diff特定の行(私の場合はコメント)をスキップするにはどうすればよいですか?grepファイルを確認し、一時ファイルを比較することを提案しないでください。

答え1

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- 違いを統合する
    • -B- 空行を無視してください
  • <(command)- bash 関数の呼び出しプロセスの交換コマンドのファイル記述子を開いて一時ファイルは必要ありません。
  • grep- パターンと一致しない行を印刷するコマンド
    • -v- 一致しない行の表示
    • E- 拡張正規表現を使用してください。
    • '^\s*(#|$)'- コメントと空白行を一致させる正規表現
      • ^- 行の先頭に一致します。
      • \s*- スペース(タブとスペース)がある場合は一致します。
      • (#|$)ハッシュタグまたは行末と一致します。

答え2

努力する:

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

正規表現は両方のファイルの対応する行と一致する必要があり、機能するにはブロック内の変更されたすべての行と一致する必要があります。それ以外の場合は、相違点が表示されます。

シェル拡張からパターンを保護し、正規表現予約文字(括弧など)をエスケープするには、単一引用符を使用します。

私たちは読むことができますdiffutils手動:

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

つまり、無視できない変更ごとにdiff無視できる変更を含め、周囲にある変更の合計を印刷します。複数-Iのオプションを使用して、無視する行に対して複数の正規表現を指定できます。diff与えられた最後の行から始めて、各行を各正規表現と一致させます。

この動作もよく説明されています。アメルはここにいます。

関連:すべてのコメントを無視するdiffを実行する方法は?

答え3

インターネットで検索してみると、Lekensteinと同様の方法が見つかりました。

diffところで、出力を入力として使用patchし、形式を変更したくてgrep -vできません。

たぶんこれが改善されたかもしれません。

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

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

ただし、コメント行の代わりに新しい行を追加すると、コメントが原因でパッチが失敗する可能性があります。

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

1つの解決策は、統合diff形式を使用しないことです-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

これでパッチファイルが機能します(ただし、より複雑な場合は保証されません)。

答え4

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

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

またはあなたがすることができます

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

関連情報