当前位置: 首页 > 后端技术 > Java

别急,别急,本文的Shell内容我一下子讲完

时间:2023-04-01 22:21:39 Java

Shell搜索匹配1.在文件中查找字符串grep命令可以搜索文件,查找指定的字符串。$grepmyvar*.c在这个例子中,我们搜索的文件都位于当前目录下。因此,我们只是使用简单的shell模式*.c来匹配以.c结尾的文件,并没有在文件名前加上路径。但并非所有要搜索的文件都老老实实地留在当前目录中。但是因为shell并不关心你输入了多少个路径名,我们也可以这样写:$grepmyvar../lib/*.c../server/*.c../cmd/*.c*/*。c如果要搜索的文件不止一个,grep会在输出前加上文件名和冒号,然后是文件中包含grep搜索内容的文本。grep的第一个(非选项)参数可以是简单的字符串或更复杂的正则表达式(regexp)。正则表达式不同于shell的模式匹配,尽管两者有时看起来很相似。一个常见的错误是忘记指定grep的输入,例如grepmyvar。在这种情况下,grep认为您正在提供来自STDIN的输入,并且您认为它会读取文件,因此grep只是等待,什么都不做。2.只显示包含搜索结果的文件名。您需要找到包含特定字符串的文件,但不想看到它所在的文本行。只输出文件名。网上经常用它来搜索配置文件。使用grep的-l选项只显示文件名,如下所示:$grep-lmyvar*.cboth.cgood.csomio.c$如果在一个文件中找到多个匹配项,grep仍然只输出一次文件名。如果未找到匹配项,则不输出任何内容。由于这些文件包含您要查找的字符串,如果您想构建一个文件列表来处理它们,-l选项会派上用场。将grep命令放入$(),然后就可以在命令行中使用这些文件名了,如下:rm-i$(grep-l'Thisfileisobsolete'*)删除字符串“Thisfileisobsolete”文件,我们在rm中添加了-i选项,以便在删除每个文件之前询问您。3.不区分大小写的搜索您想在日志文件中不区分大小写地搜索一个字符串(例如“error”)以匹配该字符串的所有出现。使用grep的-i选项忽略大小写,如下所示:grep-ierrorlogfile.log不区分大小写的搜索查找包含“ERROR”、“error”、“Error”、“ErrOR”和类似“eRrOr”的日志消息”也不例外。在查找大小写混合的单词或无法确定要查找的内容的大小时,此选项特别有用。4.减少搜索结果如果搜索返回的结果不符合预期,其中包含很多不必要的内容。将结果通过管道传递给grep-v并使用表达式来描述您不想看到的内容。假设您要在日志文件中查找整个12月的日志消息。您知道日志文件使用首字母缩略词Dec表示十二月,但您不确定情况是否总是如此。为确保找到所有日志消息,请输入以下命令:grep-ideclogfile并得到如下信息:...erroronJan01:notadecimalnumbererroronFeb13:baseconvertedtoDecimalwarningonMar22:usingonlydecimalnumbererroronDec16:TheactualmessageyouwantederroronJan01error:notadecimalnumber...有点快速和粗略解决方案是将第一个结果通过管道传递给另一个过滤掉所有“十进制”的grep。grep-idec日志文件|grep-videcimal将多个grep连接在一起并不少见(因为看不见,意想不到的匹配项不断弹出),逐步过滤搜索结果,直到您满意为止。-v选项非常方便,您只需要记住要排除的内容即可。5.搜索更复杂的模式grep中的正则表达式提供了更强大的模式匹配功能,可以满足大部分需求。正则表达式描述要匹配的字符串模式。一个字母字符(或其他对shell没有特殊意义的字符)只匹配它自己。“A”配A,“B”配B,没什么好说的。另一个重要规则是按位置组合字母,例如AB匹配“AB”。这似乎也是显而易见的。但是,正则表达式还定义了其他特殊字符,这些字符可以单独使用或与其他字符组合使用以形成更复杂的模式。第一个特殊字符是句点(.),它匹配任何单个字符。因此,....匹配任意4个字符;A.匹配“A”后跟任何单个字符;。A。匹配任何单个字符,然后是“A”,后跟任何单个字符(不一定与匹配的第一个字符相同)。第二个特殊字符,星号(*),匹配前一个字符出现0次或多次,因此A匹配0次或多次“A”字符,.*匹配0次或多次任意字符(例如“abcdefg”、“aaaabc”","sdfgf;lkjhj",甚至一个空行)。那么..*是什么意思?它匹配任何单个字符后跟任何字符的0个或多个(即一个或多个字符,但不是空行)。如下图,我们知道一行中的一些单词,想做模糊匹配,如下:grep-E"1.*22"2.text//匹配1开头,任意字符后跟22的结果如下:1898090808098822:ShellFilesearch1.Findalltxtfiles文件系统中到处都是txt文件。你想将它们集中到一个地方。那么我们该怎么做呢?find命令可以找到所有符合要求的文件,执行命令将它们移动到指定位置。例如:查找。-name'*.txt'-print-execmv'{}'/txts\;find命令的语法不同于其他Unix命令,它的选项不是典型的连字符加单个字母,后面跟着一些参数。find命令的选项看起来像短词1,按逻辑顺序出现,并描述要查找的文件以及如何处理找到的文件(如果有)。这种类似词的选项通常称为谓词。find命令的第一个参数是要搜索的目录。典型用法是使用句点(.)表示当前目录,但您也可以提供目录列表,甚至可以通过指定根目录(/)来搜索整个文件系统(只要权限允许)。示例中的第一个选项(谓词-name)指定要搜索的文件模式。它的语法类似于bash的模式匹配语法,所以*.txt可以匹配所有以“.txt”结尾的文件名。匹配该模式的文件被认为返回真(true),然后传递给下一个谓词进行处理。find遍历文件系统,将找到的文件名传递给谓词测试。如果谓词返回true,则通过。如果返回false,则不再继续,继续处理下一个文件名。谓词-print很简单。它总是返回true并将文件名打印到标准输出,因此任何通过测试到达谓词序列中这一点的文件都将打印其名称。如果未指定,则默认情况下将包含此谓词。-exec有点奇怪。到目前为止的任何文件名都将成为下一个要执行的命令的一部分。剩下的部分到\;是命令,其中{}将替换为已找到的文件名。因此,在上面的示例中,如果find在./txt/jazz子目录中找到名为1.txt的文件,则要执行的命令将是:mv./txt/jazz/1.txt/txtsallFilesmatchingthespecifiedpattern将执行命令。如果查到的文件数量多,那么命令的执行次数自然不会少。2.提高查找到文件的处理速度根据上面的例子,find命令会对每个名字符合要求的文件执行命令,但是当文件太多的时候,命令自然会很慢,那怎么办呢?我们可以提高速度吗?xargs命令从标准输入中获取以空格分隔(指定-0时除外)的文件名,并对尽可能多的文件执行指定的命令(略小于系统的ARG_MAX值,请参阅第15.13节)。由于调用其他命令的开销很大,使用xargs可以显着加快速度,因为它最大限度地减少了命令调用的次数,而不是为每个文件调用它们。如下:找到。-name'*.txt'-print|xargsmv'{}'/txts;3.查找文件时不区分大小写有些TXT文件的扩展名为.TXT而不是.txt。抬头时如何平衡两者?使用-iname谓词执行不区分大小写的搜索(如果使用的查找版本支持)。例如:查找。-iname'*.txt'-print|xargsmv'{}'/txts;4.按日期查找文件几个月前,有人给你发了一张JPEG图片,你收到并保存了起来,但现在想不起放在哪里了。我怎样才能找到这张图片?使用find命令的-mtime谓词来检查文件的最后修改日期。例如:查找。-name'*.jpg'-mtime+90-print-mtime该谓词采用一个参数指定要搜索的时间段。90代表90天。在数字前使用加号(+90)表示要搜索的文件在90天前被修改。使用减号(-90)表示文件在90天内被修改。如果既没有减号也没有加号,则表示恰好是90天。find还可以使用逻辑运算符AND、OR、NOT,如果你知道文件至少在一周(7天)前被修改过,但不超过14天前,你可以像这样组合两个谓词。如下:找到。-mtime+7-a-mtime-14-print5.按类型查找文件您正在查找名称中包含“java”一词的目录。首先尝试了以下命令。寻找。-name'*java*'-print发现文件太多,包括文件系统中的所有Java源代码文件。使用-type谓词仅选择目录。如下:找到。-typed-name'*java*'-print同样,我们可以使用-typef来指定搜索文件。我们把-typed放在前面,然后是-name'java'。两者的先后顺序不影响最终的结果,但是把-typed放在谓词列表的开头稍微提高了查找效率:对于遇到的每个文件,测试它是否是一个目录,如果是,则测试名称是否符合模式。目录比文件少。因此,这种测试顺序可以避免大多数文件进一步比较名称。6.按内容查找文件您之前写了一封重要的信件,并将其保存为扩展名为.txt的文本文件,但现在您已经记不起其余的文件名了。除此之外,我唯一记得的就是信件内容中使用了“预示”这个词。那么如何找到已知部分内容的文件呢?如果文件在当前目录中,可以使用简单的grep命令。grep-iportend*.txt如果还没有找到,我们使用更完整的解决方案:find命令。使用其-exec选项对满足谓词的文件执行命令。您可以使用grep或其他实用程序,如下所示:find。-name'*.txt'-execgrep-Hiportend'{}'\;或者您可以使用xargs查找。-名称'*.txt'|xargsgrep-嗨portendShell文本解析awk1,保留部分输出您需要一些方法来保留部分输出并丢弃其余部分。比如在我们日常的上网日志中,可能会输出很多属性,但是我们输出的大部分文本信息都可以用来解决实际问题。以下代码将打印出所有输入行的第一个字段:awk'{print$1}'myinput.file字段由空白字符分隔。实用程序awk从命令行指定的文件或标准输入(如果未指定文件)读取数据。$1代表每一行的第一列,用空格隔开。除了上面的写法,我们还可以通过管道传入:catmyinput.file|awk'{print$1}'awk的用法是可变的。最简单的用法是从输入中打印出选定的一个或多个字段。字段由空白字符分隔(您也可以使用-F选项指定分隔符),并从1开始编号。字段$0表示整个输入行。2.保留部分输入行你只想保留部分输入行,比如第一个和最后一个字段。例如,您希望ls仅列出文件名和权限,而不列出ls-l提供的其他信息。不幸的是,ls没有以这种方式限制输出的选项。您可以将ls的输出通过管道传输到awk并挑选出您需要的字段,如下所示:awk'{print$1,$NF}'总共151130-rw-r--r--添加。1drwxr-xr-xartdrwxr-xr-xbin-rw-r--r--BuddyIcon.pngdrwxr-xr-xCDsdrwxr-xr-xdownloadsdrwxr-sr-xeclipse...$如果我们使用ls-l命令输出。它具有以下形式:drwxr-xr-x2usernamegroup1762026-10-2820:09bin解析此输出对于awk来说很简单(默认字段分隔符是空格)。在输出文件名时,我们使用了一个小技巧。在awk中,各种字段都是用美元符号和字段编号来引用的(比如$1,$2,$3),awk还有一个内置变量NF,它保存的是当前行的字段总数,**$NF**始终引用最后一个字段。(例如,ls的输出行有8个字段,因此变量NF的值为8,$NF指向输入行中的第8个字段,在本例中为文件名)。注意:不需要$来读取awk变量(与bash变量不同)。NF本身是一个有效的变量引用。在它前面加上$将其含义从“当前行上的字段总数”更改为“当前行上的最后一个字段”。3.将每行中的单词倒序如果要将输入行中的单词倒序输出。通过以下脚本:$awk'{>for(i=NF;i>0;i--){>printf"%s",$i;>}>printf"\n">}'char>而不是你的输入,shell将输出这个字符来提醒你你还没有完成输入命令(shell正在寻找匹配的单引号)。由于awk程序用单引号括起来,bashshell允许我们输入多行代码,同时使用>作为辅助提示,直到我们给出与前一个匹配的结束单引号。为了可读性,我们在程序中加入了空白字符,但也可以写在一行中。$awk'{for(i=NF;i>0;i--){printf"%s",$i;}printf"\n"}'awk语言中的for循环语法和C语言很相似.我们使用for循环从最后一个字段到第一个字段进行逆向处理,同时输出每个字段的内容。4.汇总一列数字如果你需要汇总一列数字,其中一些数字没有出现在行中。先用awk筛选出要汇总的字段,再做汇总。这里我们想总结一下ls-l命令输出的文件大小。如下:ls-l|awk'{sum+=$5};END{printsum}'我们想要对ls-l输出的第5个字段求和。ls-l的输出如下所示:-rw-r--r--。1rootroot37Dec2321:442.text-rwxr--r--。1rootroot110Dec1002:20ifTest.sh的字段有:权限、链接、所有者、组、大小(以字节为单位)、最后修改日期、最后修改时间和文件名。我们只对文件大小感兴趣,因此在awk程序中使用$5来引用该字段。我们将两段awk代码放在花括号({})内,注意一个awk程序中可以有多段代码(或代码块)。以关键字END开头的代码块仅在程序的其余部分完成后运行一次。本文由传智教育博学谷教研组发布。如果本文对您有帮助,请关注并点赞;有什么建议也可以留言或私信。您的支持是我坚持创作的动力。转载请注明出处!