如何使用 grep 等解析包含多个连字符和/或空格的字符串以进行逐行处理?

如何使用 grep 等解析包含多个连字符和/或空格的字符串以进行逐行处理?

我正在 RHEL 7 和 8 上使用auditd 规则。考虑到这些示例文件...

文件2.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

文件1.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

我正在尝试使用 bash 以编程方式解析这些文件,以便检查 file2.txt 以查看它是否包含 file1.txt 中的任何行;如果是,则应从 file2.txt 中删除这些行。我不想在此过程中修改file1.txt。

期望的输出:

文件2.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(未更改):

-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

我尝试了几种不同的方法,但这可能是我得到的最接近的方法(请原谅轻微的语法错误,因为这些方法是手动转置的)。

# 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;

这会将增量放入临时文件中,但替换不起作用。我尝试过——逃避;没有不同:

sed -e expression #1: expected newer version of sed
sed -e expression #1: unknown command 'u'

双破折号转义似乎没有什么区别,例如:

sed -i -- /"$i"/d foo.txt

对于它,我也尝试过未引用:

sed -i /$i/d foo.txt

我觉得我可能错过了一些简单的东西,但我已经为此苦苦挣扎了几个小时,但还没有解开它。知道我做错了什么吗?

答案1

grep -vxFf file1.txt file2.txt > tmp.txt && mv tmp.txt file2.txt

-F代表固定字符串,因此您不会遇到特殊字符的问题。

-v正在执行与现有命令相反的操作,它正在打印不匹配的行。

-x如果我们只想匹配整行,这也是必要的。


等价awk的是这样的:

awk 'FNR==NR{a[$0]; next} !($0 in a)' file1.txt file2.txt

相关内容