If you want to match $PAT as complete lines, I have a solution. By complete lines, I mean that, in the case of a match, you can split $FILE in three sub-files (f1, f2 & f3) where:
cat f1 f2 f3 is $FILE,
- f2 is
$PAT.
Note that f1 and/or f3 can be empty.
First, create the f2 file:
cat << EOF > f2
$PAT
EOF
Then, diff $FILE and f2, saving the result:
diff $FILE f2 > diff_res
res=$?
If $res is zero, then f1 and f3 are empty, and $FILE is equal to $PAT. I will suppose that you want an empty file in this case.
If diff_res contains a line starting by ">", f2 contains at least one line not in $FILE. To test that:
grep -q '^> ' diff_res
test $? -eq 0 && echo "PAT not found"
If diff_res does not contain lines starting by ">", all lines of f2 are in $FILE, but maybe not contiguously. If it is contiguously, diff_res will contain either:
- A single line not starting with "
<" (if f1 or f3 are empty),
- Two lines not starting with "
<", the 1st always starting with "1d" or "1,".
To test this, we have:
nb=$(grep -v "^< " diff_res | wc -l)
if test $nb -gt 2; then
pat_found=0
elif test $nb -eq 1; then
pat_found=1
else
pat_found=$(sed -n -e '1{/^1d/p;/^1,/p}' diff_res | wc -l)
fi
Then, if pat_found is 1, the file without $PAT is the diff result with only the lines starting by "<" without those 2 char:
grep '^< ' diff_res | cut -c 3-
The complete and reorganized script would look like:
# Output the desired result on stdin.
f2=/tmp/f2 # Use of PID or mktmp would be better'
diff_res=/tmp/diff_res # Use of PID or mktmp would be better'
cat << EOF > $f2
$PAT
EOF
diff $FILE $f2 > $diff_res
if test $? -ne 0; then
grep -q '^> ' $diff_res
if test $? -ne 0; then
nb=$(grep -v "^< " $diff_res | wc -l)
if test $nb -eq 1; then
grep '^< ' $diff_res | cut -c 3-
elif test $nb -eq 2; then
pat_found=$(sed -n -e '1{/^1d/p;/^1,/p}' $diff_res | wc -l)
test $pat_found -eq 1 && grep '^< ' $diff_res | cut -c 3-
fi
fi
fi
rm -f $f2 $diff_res