2つのファイルAとBがありますが、ほぼ同じですが、一部の行は異なり、一部は混乱しています。これら2つのファイルはsystemverilogファイルなので、この行にはなど; , = +
の特殊文字も含まれています。
fileAの各行を繰り返して、fileBに対応する一致があるかどうかを確認したいと思います。比較は規則に従うべきです
- 先行および末尾のスペースは無視されます。
- 単語間の複数のスペース/タブを単一のスペースとして扱うことができます。
- 空行は無視できます。
結果には fileA にはあるが fileB にはない行を表示する必要があります。
試してみましたが、tkdiff
一部の線が混乱して多くの違いを示しています。
ベストアンサー1
携帯性がどれほど良いかは言えませんが、すべての基盤に対処しようとしました。あなたの情報に基づいて、テストから両方のファイルをコピーするために最善を尽くしました。 sedで特殊文字に問題がある場合は、cleanLine関数の2行目からエスケープできます。
#!/bin/bash
# compare two files and return lines in
# first file that are missing in second file
ProgName=${0##*/}
Pid=$$
CHK_FILE="$1"
REF_FILE="$2"
D_BUG="$3"
TMP_FILE="/tmp/REF_${Pid}.tmp"
declare -a MISSING='()'
m=0
scriptUsage() {
cat <<ENDUSE
$ProgName <file_to_check> <reference_file> [-d|--debug]
Lines in 'file_to_check' not present in 'reference_file'
are printed to standard output.
file_to_check: File being checked
reference_file: File to be checked against
-d|--debug: Run script in debug mode (Optional)
-h|--help: Print this help message
ENDUSE
}
# delete temp file on any exit
trap 'rm $TMP_FILE > /dev/null 2>&1' EXIT
#-- check args
[[ $CHK_FILE == "-h" || $CHK_FILE == "--help" ]] && { scriptUsage; exit 0; }
[[ -n $CHK_FILE && -n $REF_FILE ]] || { >&2 echo "Not enough arguments!"; scriptUsage; exit 1; }
[[ $D_BUG == "-d" || $D_BUG == "--debug" ]] && set -x
[[ -s $CHK_FILE ]] || { >&2 echo "File $CHK_FILE not found"; exit 1; }
[[ -s $REF_FILE ]] || { >&2 echo "File $REF_FILE not found"; exit 1; }
#--
#== edit temp file to 3 match comparison rules
# copy ref file to temp for editing
cp "$REF_FILE" $TMP_FILE || { >&2 echo "Unable to create temporary file"; exit 1; }
# rule 3 - ignore empty lines
sed -i '/^\s*$/d' $TMP_FILE
# rule 1 - ignore begin/end of line spaces
sed -i 's/^[[:space:]][[:space:]]*//;s/[[:space:]][[:space:]]*$//' $TMP_FILE
# rule 2 - multi space/tab as single space
sed -i 's/[[:space:]][[:space:]]*/ /g' $TMP_FILE
#==
# function to clean LINE to match 3 rules
# & escape '/' and '.' for later sed command
cleanLine() {
var=$(echo "$1" | sed 's/^[[:space:]][[:space:]]*//;s/[[:space:]][[:space:]]*$//;s/[[:space:]][[:space:]]*/ /g')
echo $var | sed 's/\//\\\//g;s/\./\\\./g'
}
### parse check file
while IFS='' read -r LINE || [[ -n $LINE ]]
do
if [[ -z $LINE ]]
then
continue
else
CLN_LINE=$(cleanLine "$LINE")
FOUND=$(sed -n "/$CLN_LINE/{p;q}" $TMP_FILE)
[[ -z $FOUND ]] && MISSING[$m]="$LINE" && ((m++))
FOUND=""
fi
done < "$CHK_FILE"
###
#++ print missing line(s) (if any)
if (( $m > 0 ))
then
printf "\n Missing line(s) found:\n"
#*SEE BELOW ON THIS
for (( p=0; $p<$m; p++ ))
do
printf " %s\n" "${MISSING[$p]}"
done
echo
else
printf "\n **No missing lines found**\n\n"
fi
#* using 'for p in ${MISSING[@]}' causes:
#* "SPACED LINES" to become:
#* "SPACED"
#* "LINES" when printed to stdout!
#++