bash 中的选择性差异
Selective diff in bash
我想用 diff
比较两个文件,但我想跳过一些行。我想跳过的行被标记为注释,但 仅在第一个文件中。
为了方便 copy/paste 测试,我用 process substitution:
编写了 diff
命令
$ diff -y <(echo -e "aaa\nbbb\n#ccc\nddd") <(echo -e "AAAAAA\nbbb\nccc\nddd")
aaa | AAAAAA
bbb bbb
#ccc | ccc
ddd ddd
$
可以看出第一行和第三行都被标记为差异(|
)。由于 #
符号,我不希望 diff 中的第三行。我可以使用 -I
选项忽略匹配行,但这需要两个文件都匹配模式。
$ diff -y -I "#.*" <(echo -e "aaa\nbbb\n#ccc\nddd\n#eee") <(echo -e "AAAAAA\nbbb\nccc\nddd\n#EEEE")
aaa | AAAAAA
bbb bbb
#ccc | ccc
ddd ddd
#eee #EEEE
$
有没有办法忽略仅基于第一个文件的行?
编辑:
我忘了写我需要 diff
的 return 值(echo $?
)来告诉我是否有任何不匹配的行(不包括我不想检查的行) .
使用grep -vE "^#"
筛选结果,为了得到有意义的return值可以使用wc -l
统计非普通行;
A=$(diff -y --suppress-common-lines <(echo -e "aaa\nbbb\n#ccc\nddd\neee") <(echo -e "AAAAAA\nbbb\nccc\nddd\n#EEEE") | grep -vE "^#" );
echo "$A";
return $(echo "$A" | wc -l);
输出;
aaa | AAAAAA
eee | #EEEE
return值;
2
如果您想直接在脚本中而不是在函数中使用此示例,请使用 exit
而不是 return
或 if [ $(echo "$A" | wc -l) -gt 0 ]
而不是 if [ $? -gt 0 ]
具体取决于您想要做什么,您可以根本不使用 diff
。由于您在评论中提到您的文件在行数上匹配并且您想成对比较这些行,您可以这样做:
exec 3<file1 4<file2
while read line1 <&3 && read line2 <&4; do
if [ "$line1" != "$line2" -a -n "${line1%%#*}" ]; then
echo "$line1 | $line2"
fi
done
exec 3<&- 4<&-
我也很确定这适用于任何 POSIX 兼容的 shell,而不仅仅是 bash.
我想用 diff
比较两个文件,但我想跳过一些行。我想跳过的行被标记为注释,但 仅在第一个文件中。
为了方便 copy/paste 测试,我用 process substitution:
编写了diff
命令
$ diff -y <(echo -e "aaa\nbbb\n#ccc\nddd") <(echo -e "AAAAAA\nbbb\nccc\nddd")
aaa | AAAAAA
bbb bbb
#ccc | ccc
ddd ddd
$
可以看出第一行和第三行都被标记为差异(|
)。由于 #
符号,我不希望 diff 中的第三行。我可以使用 -I
选项忽略匹配行,但这需要两个文件都匹配模式。
$ diff -y -I "#.*" <(echo -e "aaa\nbbb\n#ccc\nddd\n#eee") <(echo -e "AAAAAA\nbbb\nccc\nddd\n#EEEE")
aaa | AAAAAA
bbb bbb
#ccc | ccc
ddd ddd
#eee #EEEE
$
有没有办法忽略仅基于第一个文件的行?
编辑:
我忘了写我需要 diff
的 return 值(echo $?
)来告诉我是否有任何不匹配的行(不包括我不想检查的行) .
使用grep -vE "^#"
筛选结果,为了得到有意义的return值可以使用wc -l
统计非普通行;
A=$(diff -y --suppress-common-lines <(echo -e "aaa\nbbb\n#ccc\nddd\neee") <(echo -e "AAAAAA\nbbb\nccc\nddd\n#EEEE") | grep -vE "^#" );
echo "$A";
return $(echo "$A" | wc -l);
输出;
aaa | AAAAAA
eee | #EEEE
return值;
2
如果您想直接在脚本中而不是在函数中使用此示例,请使用 exit
而不是 return
或 if [ $(echo "$A" | wc -l) -gt 0 ]
而不是 if [ $? -gt 0 ]
具体取决于您想要做什么,您可以根本不使用 diff
。由于您在评论中提到您的文件在行数上匹配并且您想成对比较这些行,您可以这样做:
exec 3<file1 4<file2
while read line1 <&3 && read line2 <&4; do
if [ "$line1" != "$line2" -a -n "${line1%%#*}" ]; then
echo "$line1 | $line2"
fi
done
exec 3<&- 4<&-
我也很确定这适用于任何 POSIX 兼容的 shell,而不仅仅是 bash.