好吧,是的,这是一项家庭作业,但我不希望得到答案。
场景是我需要一个脚本来搜索所有用户主目录中的坏词。我需要脚本向屏幕报告某些信息,例如用户名、找到的单词和路径。它应该询问用户它是好还是坏,如果坏则将其放入坏文件名列表的文件中,如果好则从列表中删除并且不再由脚本标记。
到目前为止,我想要以某种方式进行循环。我确实知道,如果我这样做,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 命令一样,分词是通过
read
based on完成的$IFS
。因此,如果您将其设置为','
,它将根据逗号进行分割。如果您将其设置为':'
,这可能会很有用 ☺。您可以使用多种方法分割路径。
cut
可以做到,basename
并dirname
为您提供特定的零件。当然sed
也awk
可以做到,但可能有点矫枉过正。如果您使用的是 Bash,那么它的扩展扩展是最简单(也是最快)的方法。它位于手册页的“参数扩展”下。例如:$ foo='/home/bob' $ echo "${foo#/home/}" bob
更新:
我建议您不要删除特定行,而只是编写一个新文件,其中包含用户认为不正确的所有行。您可以使用类似
sed
从文件中删除一行的方法,但(在幕后)它实际上是在写入一个没有该行的新文件。一般来说,文件系统不允许您缩短文件,除非从末尾开始。提示相当简单,
read
甚至有一个选项。但你会得到一个令人惊讶的结果,因为你遗漏了5
我在示例中的所有内容。检查一下
set -x
是否可以调试。