Bash,将数组与文件进行比较,输出行不匹配

Bash,将数组与文件进行比较,输出行不匹配

我从 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

诀窍是-Fgrepwhich一起使用:

       -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,25

§ comm -23 <(echo 1 2 3 5 5 | tr ' ' '\n') <(echo 3 4 | tr ' ' '\n')
1
2
5

相关内容