Bash 脚本扫描文件中的单词并创建报告

Bash 脚本扫描文件中的单词并创建报告

好吧,是的,这是一项家庭作业,但我不希望得到答案。

场景是我需要一个脚本来搜索所有用户主目录中的坏词。我需要脚本向屏幕报告某些信息,例如用户名、找到的单词和路径。它应该询问用户它是好还是坏,如果坏则将其放入坏文件名列表的文件中,如果好则从列表中删除并且不再由脚本标记。

到目前为止,我想要以某种方式进行循环。我确实知道,如果我这样做,grep -r -e kill -e steal /home/*我会得到一份我需要的清单。我还知道该列表是由分隔符分隔的,我可以通过管道来获取我需要的变量。我还知道我可以将它放入一个文件中> filename.txt

我不知道如何启动一个循环来做到这一点......

 for each line in filename.txt
 UNAME=...
 LOC=...
 TXT=...
 echo "Username: $UNAME, Line with bad word found: $TXT, and Path and file name: $LOC. Is this a BAD file? (Y)"
 Read YORN

 if ["$YORN" = "Y" ]; then
 >> (line of text from grep) badfiles.txt
 fi

接下来或者无论发生什么......

要求:创建一个脚本来运行以查找不良单词,例如(至少)炸弹、杀死、用空格分隔的我们的全名、退出和窃取。您必须运行一次以向屏幕报告并找到所有显示 1- 用户名 2- 包含错误单词的行以及 3- 路径和文件名的文档。然后,我们应该更改脚本或对其执行某些操作,以便我们知道文件在哪里,然后忽略具有合法用途的文件,例如终止进程或退出程序(删除标志)

我所做的:我创建了用户和文档来测试包括这些词。我已经运行了我的脚本(如下)并将命令的输出放入一个文件中,然后逐行循环该文件。现在我只是让它回显我的变量来看看我是否走在正确的轨道上......

脚本:

grep -r -e kill -e Anne -e bomb -e quit -e steal /home/* > /opt/badword.txt

while read line
do
LOC=`echo -e "$line" | cut -d : -f 1`
TXT=`echo -e "$line" | cut -d : -f 2`
UNAME=`echo -e "$line" | cut -d "/" -f 3`
echo $LOC
echo $TXT
echo $UNAME
done <badword.txt

运行此脚本的屏幕输出:

[root@AnneCentOS opt]# ./script4
/home/brownb/doc1
hello my name is xxx i am going to plant a bomb
brownb
/home/brownb/doc2
I want to kill you
brownb
/home/mammaj/doc67
kill process
mammaj
/home/mammaj/doc22
Anne needs to go
mammaj
/home/swiftt/doc
I want to steal a bunch of money so i never have to work again
swiftt
/home/swiftt/doc300
I want to quit this job!
swiftt
[root@AnneCentOS opt]# 

在我的 badword.txt 中:

/home/brownb/doc1:hello my name is xxx i am going to plant a bomb
/home/brownb/doc2:I want to kill you
/home/mammaj/doc67:kill process
/home/mammaj/doc22:Anne needs to go
/home/swiftt/doc:I want to steal a bunch of money so i never have to work again
/home/swiftt/doc300:I want to quit this job!

最后我想在每一行后面添加一行来询问用户这是一个好文件吗?我想添加一个 if 语句,如果答案 = Y 那么我可以从 badword.txt 中删除该行,我想我知道如何创建问题,而 if 语句只是不知道是否有办法删除特定的我创建的文档中的行。

答案1

一些提示:

  • 您计划仅扫描 /home 来查找所有主目录。它可能远远超出了 Linux 入门课程的范围,但实际上不适用于更复杂的设置。getent passwd可能会好一点,但这肯定超出了 Linux I 的范围。

  • 我不完全清楚你是否在文件中寻找坏词名字或者内容。如果是名称,find是搜索文件名的简单方法 ( find PATHS '(' -iname '*badword1*' -or -iname '*badword2*' -or … ')' -print)

  • 如果您正在查看内容,这grep确实是正确的选择。您可能想让-H它始终打印文件名。-n(打印行号,从 1 开始计数)或-b(打印字节偏移量)也可能有用。或者,-l只会为您提供匹配的文件名。 (此外,并非所有文件都是纯文本;二进制文件的结果可能很奇怪)。

  • 从文件读取的 shell 命令是read.由于您计划在循环期间提示用户,因此您必须从 stdin 以外的其他地方读取(通过传递-u)。通常,您会在while循环中使用它。另请注意,重定向来自命令——在这种情况下,命令就是整个循环!

    while read -r -u 5 WORD1 WORD2; do
        true   # do something with $WORD1 and $WORD2 here
    done 5<filename.txt
    
  • 与几乎所有 shell 命令一样,分词是通过readbased on完成的$IFS。因此,如果您将其设置为',',它将根据逗号进行分割。如果您将其设置为':',这可能会很有用 ☺。

  • 您可以使用多种方法分割路径。cut可以做到,basenamedirname为您提供特定的零件。当然sedawk可以做到,但可能有点矫枉过正。如果您使用的是 Bash,那么它的扩展扩展是最简单(也是最快)的方法。它位于手册页的“参数扩展”下。例如:

    $ foo='/home/bob'
    $ echo "${foo#/home/}"
    bob
    

更新:

  • 我建议您不要删除特定行,而只是编写一个新文件,其中包含用户认为不正确的所有行。您可以使用类似sed从文件中删除一行的方法,但(在幕后)它实际上是在写入一个没有该行的新文件。一般来说,文件系统不允许您缩短文件,除非从末尾开始。

  • 提示相当简单,read甚至有一个选项。但你会得到一个令人惊讶的结果,因为你遗漏了5我在示例中的所有内容。

  • 检查一下set -x是否可以调试。

相关内容