J'ai deux files de configuration, l'original du gestionnaire de packages et un file personnalisé modifié par moi-même. J'ai ajouté quelques commentaires pour décrire le comportement.
Comment puis-je lancer diff
sur les files de configuration, en sautant les commentaires? Une ligne commentée est définie par:
#
) L'expression régulière (la plus simple) ignorant la première exigence serait #.*
. J'ai essayé l' --ignore-matching-lines=RE
( -I RE
) de GNU diff 3.0, mais je ne pouvais pas le faire fonctionner avec cet ER. J'ai aussi essayé .*#.*
Et .*\#.*
Sans chance. Littéralement mettre la ligne ( Port 631
) comme RE
ne correspond à rien, ni aider à mettre le RE entre les barres obliques.
Comme suggéré dans "diff" la saveur de regex semble manquer? , J'ai essayé grep -G
:
grep -G '#.*' file
Cela semble correspondre aux commentaires, mais cela ne fonctionne pas pour diff -I '#.*' file1 file2
.
Alors, comment cette option devrait-elle être utilisée? Comment puis-je faire diff
sauter certaines lignes (dans mon cas, commentaires)? Veuillez ne pas suggérer de grep
le file et de comparer les files temporaires.
Selon Gilles, l'option -I
ignore seulement une ligne si rien d'autre à l'intérieur de cet set ne correspond, sauf pour la correspondance de -I
. Je ne l'ai pas complètement compris avant de l'avoir testé.
Trois files sont impliqués dans mon test: Fichier test1:
text
Fichier test2:
text #comment
Fichier test3:
changed text #comment
Les commands:
$ # 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
Comme il n'y a pas de réponse à ce jour expliquant comment utiliser l'option -I
correctement, je vais vous proposer une alternative qui fonctionne dans les shell bash:
diff -u -B <(grep -vE '^\s*(#|$)' test1) <(grep -vE '^\s*(#|$)' test2)
diff -u
– diff unifié
-B
– ignore les lignes vides <(command)
– une fonctionnalité bash appelée substitution de process qui ouvre un descripteur de file pour la command, ce qui supprime le besoin d'un file temporaire grep
– command pour l'printing de lignes (non) correspondant à un motif
-v
– affiche les lignes non-appariées E
– utiliser des expressions régulières étendues '^\s*(#|$)'
– une expression régulière correspondant aux commentaires et aux lignes vides ^
– correspond au début d'une ligne \s*
– correspond à des espaces (tabulations et espaces) le cas échéant (#|$)
correspondent à une marque de hachage, ou bien la fin d'une ligne Essayer:
diff -b -I '^#' -I '^ #' file1 file2
S'il vous plaît noter que l'expression régulière doit correspondre à la ligne correspondante dans les deux files et il correspond à chaque ligne modifiée dans le morceau pour fonctionner, sinon il affichera toujours la différence.
Utilisez des guillemets simples pour protéger le model du shell en expansion et pour échapper aux caractères réservés aux expressions rationnelles (par exemple, des parenthèses).
Nous pouvons lire dans le manuel diffutils
:
Cependant,
-I
seulement l'insertion ou la suppression des lignes qui contiennent l'expression régulière si chaque ligne modifiée dans le morceau (chaque insertion et chaque suppression) correspond à l'expression régulière.En d'autres termes, pour chaque changement non ignorable,
diff
imprime l'set complet des changements à proximité, y compris les changements ignorables. Vous pouvez spécifier plus d'une expression régulière pour les lignes à ignorer en utilisant plusieurs options-I
.diff
essaie de faire correspondre chaque ligne à chaque expression régulière, en commençant par la dernière donnée.
Ce comportement est également bien expliqué par armel ici .
J'ignore habituellement ce fouillis par l'un ou l'autre:
grep -v "^#" | cat -s
grep -v "^#" | cat -s
et en différant ceux ou … vim -d
pour regarder les files. La mise en surbrillance de la syntaxe prend soin de rendre évidente les différences entre les commentaires et les non-commentaires. La mise en surbrillance diff de la différence en ligne pour que vous puissiez voir quelles valeurs ou parties de valeurs ont été changées en un coup d'oeil en font mon préféré. Après la search sur le web, le path alternatif de Lekensteyn est le meilleur que j'ai trouvé.
Mais je veux utiliser la sortie dif en tant que patch … et il y a un problème parce que le numéro de ligne est noté à cause de "grep -v".
J'ai donc l'intention d'améliorer cette command line:
diff -u -B <(sed 's/^[[:blank:]]*#.*$/ /' file1) <(sed 's/^[[:blank:]]*#.*$/ /' file2)
Ce n'est pas parfait, mais le numéro de ligne est conservé dans le file correctif.
Cependant, si une nouvelle ligne est ajoutée à la place de la ligne de commentaire … le commentaire produira un Hunk FAILED lors du patch comme nous pouvons le voir ci-dessous.
File test1: text #comment other text File test2: text new line here #comment changed other text changed
teste maintenant notre command
$ 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 sont des files produits par substitution de process. La ligne entre "+ nouvelle ligne" et "-autre text" est le caractère d'espace par défaut défini dans notre expression sed pour replace les commentaires.
Et maintenant, que se passe-t-il lorsque nous appliquons ce correctif:
$ 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
La solution est de ne pas utiliser un format diff unifié sans -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
maintenant file de travail de file de correction (sans garantie de résultat dans le process de diff très complexe).
Voici ce que j'utilise pour supprimer toutes les lignes commentées – même celles commençant par un onglet ou un espace – et les lignes vides:
egrep -v "^$|^[[:space:]]*#" /path/to/file
ou vous pouvez faire
sed -e '/^#.*/d' -e 's/#.*//g' | cat -s