it-swarm-eu.dev

Jak rozlišit soubory ignorující komentáře (řádky začínající na #)?

Mám dva konfigurační soubory, originál ze správce balíků a jeden upravený, který jsem sám upravil. Přidal jsem několik komentářů k popisu chování.

Jak mohu spustit diff v konfiguračních souborech a přeskočit komentáře? Řádek s komentářem je definován:

  • volitelný úvodní mezera (karty a mezery)
  • hash sign (#)
  • cokoli jiného charakteru

(Nejjednodušší) regulární výraz přeskakující první požadavek by byl #.*. Zkusil jsem --ignore-matching-lines=RE (-I RE) možnost GNU diff 3.0, ale nemohl jsem si s ní pracovat s RE. Také jsem se pokusil .*#.* a .*\#.* bez štěstí. Doslovně uvedení řádku (Port 631) protože RE neodpovídá ničemu, ani nepomáhá umístit RE mezi lomítka.

Jak je naznačeno v zdá se, že chuť regexu „diff“ chybí? , zkusil jsem grep -G:

grep -G '#.*' file

Zdá se, že to odpovídá komentářům, ale pro diff -I '#.*' file1 file2.

Jak by tedy měla být tato možnost použita? Jak mohu donutit diff přeskočit určité řádky (v mém případě komentáře)? Nenavrhujte prosím greping souboru a porovnání dočasných souborů.

56
Lekensteyn

Podle Gilles volba -I Ignoruje řádek pouze v případě, že se uvnitř této sady neodpovídá nic jiného než zápas -I. Dokud jsem to nezkoušel, nedostal jsem ho úplně.

Test

Do mého testu jsou zapojeny tři soubory:
Soubor test1:

    text

Soubor test2:

    text
    #comment

Soubor test3:

    changed text
    #comment

Příkazy:

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

Alternativní způsob

Protože zatím neexistuje odpověď, která by vysvětlovala, jak správně používat možnost -I, Poskytnu alternativu, která funguje v bash shellech:

diff -u -B <(grep -vE '^\s*(#|$)' test1)  <(grep -vE '^\s*(#|$)' test2)
  • diff -u - sjednocený rozdíl
    • -B - ignorovat prázdné řádky
  • <(command) - bash funkce nazvaná substituce proces , která otevře popisovač souboru pro příkaz, odstraní to potřebu dočasného souboru
  • grep - příkaz pro tisk řádků (ne) odpovídajících vzoru
    • -v - zobrazí neodpovídající řádky
    • E - použijte rozšířené regulární výrazy
    • '^\s*(#|$)' - regulární výraz odpovídající komentářům a prázdným řádkům
      • ^ - odpovídá začátku řádku
      • \s* - shodujte mezery (tabulátory a mezery), pokud existují
      • (#|$) Odpovídá hashovací značce nebo alternativně konci řádku
54
Lekensteyn

Snaž se:

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

Vezměte prosím na vědomí, že regex musí odpovídat odpovídajícímu řádku v obou souborech a odpovídá každému změněnému řádku v kusu, aby fungoval, jinak bude stále zobrazovat rozdíl.

Použijte jednoduché uvozovky k ochraně vzoru před rozšířením prostředí Shell a k úniku před regexem vyhrazenými znaky (např. Závorky).

Můžeme číst diffutils manuál:

Nicméně, -I ignoruje vkládání nebo mazání řádků, které obsahují regulární výraz, pouze pokud se každý změněný řádek v kusu (každé vložení a každé vymazání) shoduje s regulárním výrazem.

Jinými slovy, pro každou nevysvětlitelnou změnu diff vytiskne úplnou sadu změn v jejím okolí, včetně těch, které lze ignorovat. Můžete zadat více než jeden regulární výraz pro řádky, které se mají ignorovat, pomocí více než jednoho -I možnost. diff se snaží porovnat každý řádek s každým regulárním výrazem, počínaje posledním daným výrazem.

Toto chování je také dobře vysvětleno zde armel .

Související: Jak mohu provést rozdíl, který ignoruje všechny komentáře?

7
kenorb

Po prohledávání webu je alternativní způsob Lekensteyn tím lepším, co jsem našel.

Ale chci použít dif výstup jako patch ... a je tu problém, protože číslo řádku je zachováno kvůli "grep -v".

Účelem je vylepšit tento příkazový řádek:

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

Není to dokonalé, ale číslo řádku je uloženo v opravném souboru.

Pokud však místo řádku s komentářem bude přidán nový řádek ... komentář vytvoří při opravě Hunk FAILED, jak můžeme vidět níže.

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

vyzkoušejte nyní náš příkaz

$ 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 jsou soubory vytvořené substitucí procesu. Řádek mezi „+ novým řádkem“ a „jiným textem“ je výchozí znak mezery definovaný v našem sedu, který nahrazuje komentáře.

A teď, co se stane, když použijeme tuto opravu:

$ 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

Řešením je nepoužívat unifikovaný formát diff bez -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

nyní oprava souboru pracovní soubor (bez záruky výsledku ve velmi složitém procesu diff).

3
syjust

Tento nepořádek obvykle ignoruji buď:

  • Generování nekomentovaných verzí pomocí grep -v "^#" | cat -s a jejich rozdíly nebo ...
  • Použitím vim -d prohlédnout si soubory. Zvýraznění syntaxe se postará o to, aby byly rozdíly mezi komentáři a bez komentářů zcela zřejmé. Rozdílné zvýraznění in-line rozdílu, takže můžete vidět, jaké hodnoty nebo části hodnot byly na první pohled změněny, je moje oblíbená.
1
Caleb

Zde je to, co používám k odstranění všech komentovaných řádků - z těch, které začínají tabulátorem nebo mezerou - a prázdných:

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

nebo můžete

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