I'm working with auditd rules on RHEL 7 and 8. Considering these example files...
file2.txt:
-a always,exit -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete
-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod
-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d/ -p wa -k actions
file1.txt:
-a always,exit -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete
-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
I'm trying to parse these files programmatically with bash such that file2.txt is checked to see if it contains any of the lines in file1.txt; if it does, those lines should be deleted from file2.txt. I do not want to modify file1.txt in this process.
Desired output:
file2.txt:
-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>=1000 -F auid!=unset -F key=perm_mod
-w /etc/sudoers -p wa -k actions
-w /etc/sudoers.d/ -p wa -k actions
file1.txt (unchanged):
-a always,exit -S unlink -S unlinkat -S rename -S renameat -F auid>=1000 -F auid!=4294967295 -k delete
-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>=1000 -F auid!=unset -F key=perm_mod
I've tried a few different approaches, but this is probably the closest I've gotten (excuse minor syntactical errors, as these are transposed by hand).
# Write deltas to a temporary file
grep -f file2.txt file1.txt >> temp_file.txt
For each line in the temporary delta file, delete that line from file2.txt
for i in $(cat temp_file.txt); do
sed -i /"$i"/d file2.txt
done;
This gets the deltas into a temp file, but then the replacement doesn't work. I've tried -- escaping; no difference:
sed -e expression #1: expected newer version of sed
sed -e expression #1: unknown command 'u'
Double-dash escaping seems to make no difference, e.g.:
sed -i -- /"$i"/d foo.txt
For the heck of it, I've also tried unquoted:
sed -i /$i/d foo.txt
I feel like I'm probably missing something simple, but I've bashed my head against this for a few hours and I haven't unraveled it. Any idea what I'm doing wrong?
file2.txt
as patterns and then remove the patterns infile2.txt
that match anything infile1.txt
? – Kusalananda May 06 '22 at 13:22grep -vFf
(orawk
orsed
at once), no need to parse their delta. But could you have lines with the options in different order, that will not be considered as duplicates? Or this can't be. – thanasisp May 06 '22 at 13:24sed -i /"$i"/d
vs.sed -i -- /"$i"/d
vs.sed -i /$i/d
one issue you get there is that your data contains slashes, so the$i
will at some point expand to/etc/sudoers
, so sed sees//etc/sudoers/d
. Quotes are a shell thing, and what sed does with what it gets is different. See Why does my shell script choke on whitespace or other special characters?, https://mywiki.wooledge.org/Quotes and/or https://mywiki.wooledge.org/WordSplitting for the thing about the quotes. – ilkkachu May 06 '22 at 14:56for i in $(cat temp_file.txt)
is seldom what you want, because you get splitting on whitespace by default, not lines (see the above links).while IFS= read -r line; do ... done < file
might be better, see e.g. Understanding "IFS= read -r line" and Busy box Read file line by line – ilkkachu May 06 '22 at 14:58