我从 RHEL 计算机上的日志文件列表中收集了一个字符串数组,我想识别数组中在文件中没有相同匹配行的唯一行,但我无法用谷歌 :-(
这个收集数组的位工作正常
IFS=$'\n'
Z=( $(/usr/bin/grep -ir --exclude="*_audit.log" ' error' /var/log/*.log | grep "$(date +"%b %_d")" | grep -sv "$non_issue") )
我无法弄清楚循环 Z 并检查日志文件中是否有匹配的行。
if line in Z does not match any line in /report.log #repeat for each line in Z
then
echo this unique line
fi
文本行是日志文件输出,因此其中有很多特殊字符,例如/
、"
、:
等。
答案1
怎么样:
IFS=$'\n'
## avoid using CAPS for shell variable names since global env vars are
## capitalized by convention and if yours are also caps, you can have naming collisions
z=( $(/usr/bin/grep -ir --exclude="*_audit.log" ' error' /var/log/*.log |
grep "$(date +"%b %_d")" | grep -sv "$non_issue") )
for line in "${z[@]}"; do
grep -qF "$line" /report.log &&
printf '%s\n' "$line"
done
诀窍是-F
与grep
which一起使用:
-F, --fixed-strings
Interpret PATTERNS as fixed strings, not regular expressions.
因此-F
,将grep
其输入视为常规字符串来查找 =,忽略任何特殊字符。接下来,这-q
意味着“不打印任何内容”,但只有找到该行,整个事情才会成功。这&&
意味着“仅当上一个命令成功时才运行下一个命令”,因此,如果找到该行,那么我们将打印它。
答案2
有的是comm
命令可以显示一个文件中不存在于另一个文件中的行。假设从日志文件中收集的字符串确实是完全相同的(即,将匹配所有的行/report.log
)到您正在检查的主文件中,您可以这样做:
comm -23 <(/usr/bin/grep -ir --exclude="*_audit.log" ' error' /var/log/*.log |
grep "$(date +"%b %_d")" | grep -sv "$non_issue" | sort | uniq) \
<(sort /regions.log | uniq)
默认情况下,该命令输出三条信息:仅在第一个文件中的行、仅在第二个文件中的行以及两个文件中的行。该-23
开关会抑制最后两个文件的输出,从而在第一个文件中留下唯一的行。请注意,该命令需要排序的文件。
如果您不熟悉语法<( <some-command-pipeline> )
,那就是过程替代bash
。您可以将其视为bash
将 的输出通过管道传输<some-command-pipeline>
到临时文件,然后将该文件名传递给comm
.因此,这种技术可以让您免于创建临时文件,然后在这些文件上运行命令。
这是一个简单的示例comm
,可以解释您的问题:您想要在第一个文件中查找第二个文件中不存在的行(为了方便起见,再次通过进程替换创建)。在这种情况下,那就是1
,2
和5
:
§ comm -23 <(echo 1 2 3 5 5 | tr ' ' '\n') <(echo 3 4 | tr ' ' '\n')
1
2
5