[转帖]别催了,别催了,这篇文章我一次性把 Shell 的内容说完

篇文章,一次性,shell,内容,说完 · 浏览次数 : 0

小编点评

这段内容包含多个关于查找文件和汇总数字列表的 awk 代码片段,并结合了对文件大小的分析。以下是一段解析代码片段的详细说明: 1. **查找文件并获取文件名:** `$ ls -l | awk '{print $1, $NF}'total 151130-rw-r--r-- add.1drwxr-xr-x artdrwxr-xr-x bin-rw-r--r-- BuddyIcon.pngdrwxr-xr-x CDsdrwxr-xr-x downloadsdrwxr-sr-x eclipse...$` - 此代码片段首先使用 `$ ls -l` 命令输出所有文件名,并使用 `awk '{print $1, $NF}'` 的代码片段对文件名和每个字段的值进行打印,最后使用 `total`字段统计所有文件名数量。 2. **保留部分输入行:** `$ awk '{> for (i=NF; i>0; i--) {> printf \"%s \", $i;> }> printf \"\\"}'` - 此代码片段使用 `$ awk '{> for (i=NF; i>0; i--) {> printf \"%s \", $i;> }> printf \"\\"}'` 的代码段保留所有输入行的第一个字段。 3. **颠倒每行的单词:** `$ awk '{> for (i=NF; i>0; i--) {> printf \"%s \", $i;} printf "\\"}'` - 此代码片段使用 `$ awk '{> for (i=NF; i>0; i--) {> printf \"%s \", $i;} printf "\\"}'` 的代码段对每个字段的值进行打印,并最后使用 `\\`字符将所有字段的内容输出到一行结束。 4. **汇总数字列表:** `$ awk '{sum += $5}; END {print sum}'` - 此代码片段使用 `$ awk '{sum += $5}; END {print sum}'` 的代码段对所有文件大小的总和进行计算,并使用 `END {print sum}` 的代码段将结果打印到一行结束。 5. **合并多个文件大小:** `ls -l | awk '{sum += $5}; END {print sum}'` - 此代码片段使用 `ls -l | awk '{sum += $5}; END {print sum}'` 的代码段先过滤出待汇总的字段,然后做汇总。 总结此段内容,它展示了如何使用 awk进行文件查找、保留部分输入、颠倒每行的单词、汇总数字列表以及合并多个文件大小等操作。这些代码片段结合了 awk的语法和awk的代码片段,在进行文件查找和分析时展现了awk的强大功能。

正文

https://my.oschina.net/jiagoushi/blog/6037198

 

 

Shell 搜索与匹配

1、在文件中查找字符串

grep 命令可以搜索文件,查找指定的字符串。

$ grep myvar *.c

在这个例子中,我们搜索的文件全都位于当前目录下。因此,我们只使用了简单的 shell 模式 *.c 来匹配以 .c 结束的文件,并没有在文件名前再添加路径。

但并非所有待搜索的文件都老老实实地待在当前目录下。但因为 shell 并不在意你输入多少路径名,所以我们也可以这么写:

$ grep myvar ../lib/*.c ../server/*.c ../cmd/*.c */*.c

如果待搜索的文件不止一个,grep 会在输出前加上文件名以及冒号,然后是该文件中包含 grep 搜索内容的文本。

grep 的第一个(非选项)参数可以是一个简单的字符串,也可以是更复杂的正则表达式(regexp)。正则表达式不同于 shell 的模式匹配,尽管两者有时看起来差不多。

常见错误

忘记指定 grep 的输入,例如 grep myvar。这种情况下,grep 会认为你要从 STDIN 提供输入,而你以为它会读取文件,于是 grep 就干等着,无所事事。

2、只显示包含搜索结果的文件名

你需要找出包含特定字符串的文件,但是不想看到其所在的文本行,只用输出文件名即可,经常在线上为了搜索配置文件。

用 grep 的 -l 选项仅显示文件名即可,如下:

$ grep -l myvar *.c
both.c
good.c
somio.c
$

如果在一个文件中找到了多次匹配,grep 仍然只输出该文件名一次。如果没有找到匹配,则什么都不输出。

由于这些文件包含了你要查找的字符串,如果想据此构建一个待处理

文件的列表,选项 -l 就能派上用场了。将 grep 命令放进 $(),然后就可以在命令行上使用这些文件名了,如下:

rm -i $(grep -l 'This file is obsolete' * ) 

删除包含字符串 “This file is obsolete” 的文件,我们给 rm 加上了 -i 选项,以便在删除每个文件前都先询问你。

3、不区分大小写搜索

你想要在日志文件中不区分大小写地搜索字符串(如 “error”),以匹配该字符串的所有出现。用 grep 的 -i 选项忽略大小写,如下所示:

grep -i error logfile.log

不区分大小写的搜索能够找出包含 “ERROR”、“error”、“Error” 的日志消息,“ErrOR” 和 “eRrOr” 这样的也不例外。该选项在查找大小写混合的单词时尤其管用,或者对于查找的内容无法确定大小时。

4、缩减搜索结果

如果搜索返回的结果不符合预期,其中包括许多并不需要的内容。将结果通过管道传给 grep -v 并用表达式描述出你不想看到的内容。假设你想在日志文件中找出整个 12 月的日志消息。你知道日志文件用字母缩写 Dec 代表 12 月,但不敢肯定总是如此,为了确保找出所有的日志消息,输入下列命令:

grep -i dec logfile

得到的结果却如下所示:

...
error on Jan 01: not a decimal number
error on Feb 13: base converted to Decimal
warning on Mar 22: using only decimal numbers
error on Dec 16 : the actual message you wanted
error on Jan 01: not a decimal number
...

一种快而糙的解决方案是,将第一次得到的结果通过管道传给另一个 grep,由后者过滤掉所有的 “decimal”。

grep -i dec logfile | grep -vi decimal

将多个 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:  

Shell 文件查找

1、查找所有的 txt 文件

文件系统中到处都是 txt 文件。你想将它们集中到一个位置。那么我们该如何做呢?

find 命令可以找出符合要求的所有文件并执行命令,将其移动到指定位置。例如:

find . -name '*.txt' -print -exec mv '{}'  /txts  \;

find 命令的语法和其他 Unix 命令不同,其选项并不是那种典型的连字符加上单字母,后面再跟上若干参数。find 命令的选项看起来像是简短的单词 1,依照逻辑顺序出现,并描述要查找哪些文件以及如何处理找到的文件(如果存在的话)。这种像单词一样的选项通常称为谓词(predicate)。

find 命令的第一个参数是待搜索的目录。典型用法是用点号(.)代表当前目录,不过你也可以提供一个目录列表,甚至通过指定根目录(/)来搜索整个文件系统(只要权限允许)。

示例中的第一个选项(谓词 -name)指定了要搜索的文件模式。其语法和 bash 的模式匹配语法差不多,因此 *.txt 能够匹配所有以 “.txt” 结尾的文件名。匹配该模式的文件被认为返回的是真(true),接着将其交给下一个谓词进行处理。

find 会遍历文件系统,将找到的文件名交给谓词测试。如果谓词返回真,就通过。如果返回假,则不再继续往下进行,会接着处理下一个文件名。

谓词 -print 很简单。它总是返回真,同时会将文件名打印到标准输出,因此,能在谓词序列中通过测试而到达这一步的文件都会输出其名称。如果不写,默认会带有这个谓词。

-exec 就有点怪异了。到达这一步的文件名都会变成接下来要执行的命令的一部分。剩下一直到;的这部分就是命令,其中的 {} 会被替换成已查找到的文件名。因此,在上面的例子中,如果 find 在./txt/jazz 子目录中找到名为 1.txt 的文件,那么要执行的命令就会是:

mv ./txt/jazz/1.txt  /txts

所有匹配指定模式的文件都会执行命令。如果找到的文件数量众多,那么命令的执行次数自然也不会少。

2、提升已找到文件的处理速度

按照上面的例子,find 命令会为每个名字符合要求的文件执行命令,但是当文件过多时命令自然会很慢,那么我们如何提高速度呢?

xargs 命令从标准输入中接收以空白字符分隔(指定 -0 时除外)的文件名,然后对尽可能多的文件(略微少于系统的 ARG_MAX 值,参见 15.13 节)执行指定命令。由于调用其他命令会带来不小的开销,因此使用 xargs 可以显著提升操作速度,因为它能够尽量减少命令的调用次数,而不是每个文件都调用。如下所示:

find . -name '*.txt' -print  | xargs  mv '{}'  /txts;

3、查找文件时不区分大小写

有些 TXT 文件的扩展名是 .TXT,而不是 .txt。查找时该如何兼顾两者?

用 -iname 谓词(如果使用的 find 版本支持)执行不区分大小写的搜索。例如:

find . -iname '*.txt' -print  | xargs  mv '{}'  /txts;

4、按日期查找文件

几个月前,有人给你发了一张 JPEG 图片,你接收后就保存了起来,但现在记不清放哪了。怎样才能找到这张图片呢?

使用 find 命令的 -mtime 谓词来检查文件的最后修改日期。例如:

find . -name '*.jpg' -mtime +90 -print

-mtime 谓词接受一个参数,用于指定要搜索的时间段。90 代表 90 天。在数字前使用加号(+90)表明要搜索的文件是在 90 天前修改的。使用减号(-90)表明文件是在 90 天以内修改的。如果既没减号,也没加号,则表明正好就是 90 天。

find 还可以使用逻辑运算符 AND、OR、NOT,如果知道文件修改时间至少在一周(7 天)前,但不超过 14 天,那么就可以像下面这样将两个谓词结合起来。如下所示:

find . -mtime +7 -a -mtime -14 -print

5、按类型查找文件

你正在查找名称中带有单词 “java” 的目录。先尝试了以下命令。

find . -name '*java*' -print

找到的文件太多了,其中还包括文件系统中所有的 Java 源代码文件。使用 -type 谓词只选择目录。如下:

find . -type d -name '*java*' -print

同样,我们可以使用 -type f 指定指查找文件。

我们将 -type d 放在前面,然后是 -name 'java'。两者的顺序并不影响最终结果,但将 -type d 放在谓词列表的最前面能略微提高搜索效率:对于碰到的每个文件,先测试其是否为目录,如果是,才测试名称是否符合模式。目录的数量比文件要少一些。因此,这种测试顺序使得大部分文件不用再进一步比较名称了。

6、按内容查找文件

你之前写了一份重要的信件,并将其保存为以 .txt 为扩展名的文本文件,但现在想不起文件名的其余部分了。除此之外,唯一记得的就是信件内容中用到过单词 “portend”。那么该如何查找已知部分内容的文件呢?

如果文件就在当前目录下,可以使用简单的 grep 命令。

grep -i portend *.txt

如果还没找到,我们换用一个更完备的解决方案:find 命令。使用其 -exec 选项对满足谓词的文件执行命令。你可以按下列方式使用 grep 或其他实用工具:

find . -name '*.txt' -exec grep -Hi portend '{}' \;

或者也可以使用 xargs

find . -name '*.txt' | xargs grep -Hi portend

Shell 文本解析 awk

1、保留部分输出

你需要用某种方法保留部分输出,丢弃其余输出。比如我们日常线上日志,我们可能会输出很多属性,但是真正能用来解决实际问题的,大多是我们输出的文字信息。以下代码会打印出所有输入行的第一个字段:

awk '{print $1}' myinput.file

字段之间以空白字符分隔。实用工具 awk 从命令行上指定的文件中读取数据,如果没有指定文件,则从标准输入读取。$1 代表每行以空格分割后的第一列。

除了上面的写法,我们还可以通过管道传入:

cat myinput.file | awk '{print $1}'

awk 的用法多变。最简单的用法就是从输入中打印出所选的一个或多个字段。字段之间以空白字符分隔(也可以用 -F 选项指定分隔字符),编号从 1 开始。字段 $0 代表整个输入行。

2、保留部分输入行

你只想保留部分输入行,例如第一个和最后一个字段。举例来说,你希望 ls 只列出文件名和权限,不需要 ls -l 所提供的其他信息。可惜的是,ls 并没有相应的选项能够按照这种方式限制输出。可以通过管道将 ls 的输出传给 awk,并从中挑选出你需要的字段,如下:

$ ls -l | awk '{print $1, $NF}'
total 151130
-rw-r--r-- add.1
drwxr-xr-x art
drwxr-xr-x bin
-rw-r--r-- BuddyIcon.png
drwxr-xr-x CDs
drwxr-xr-x downloads
drwxr-sr-x eclipse
...
$

如果我们用 ls -l 命令的输出。其形式如下所示:

drwxr-xr-x 2 username group 176 2026-10-28 20:09 bin

对于 awk 而言,解析这种输出易如反掌(在 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"
> }' <filename>

字符 > 不用你输入,shell 会输出该字符来提醒你还没有敲完命令(shell 在查找能配对的单引号)。由于 awk 程序位于单引号中,因此 bash shell 允许我们输入多行代码,同时使用 > 作为辅助提示符,直到我们给出与先前匹配的结束单引号。考虑到可读性,我们在程序中加入了空白字符,不过也完全可以写成一行。

$ awk '{for (i=NF; i>0; i--) {printf "%s ", $i;} printf "\n"}' <filename>

awk 语言的 for 循环语法和 C 语言中的非常相似。我们用 for 循环从最后一个字段开始倒着处理到第一个字段,同时输出每个字段的内容。

4、汇总数字列表

如果你需要汇总数字列表,其中有些数字并未出现在行中。用 awk 先过滤出待汇总的字段,然后再做汇总。这里我们要对 ls -l 命令输出的文件大小进行汇总。如下:

ls -l | awk '{sum += $5}; END {print sum}'

我们要汇总 ls -l 输出的第 5 个字段。ls -l 的输出如下所示:

-rw-r--r--. 1 root root  37 1223 21:44 2.text                                           
-rwxr--r--. 1 root root 110 1210 02:20 ifTest.sh

各个字段分别为:权限、链接、所有者、所属组、大小(以字节为单位)、最后一次修改日期、最后一次修改时间,以及文件名。我们只对文件大小感兴趣,因此在 awk 程序中用 $5 来引用该字段。我们在花括号({})里放置了两段 awk 代码,注意,awk 程序中可以有多个代码段(或代码块)。前有关键词 END 的代码块仅在程序其他部分完成后运行一次。

与[转帖]别催了,别催了,这篇文章我一次性把 Shell 的内容说完相似的内容:

[转帖]别催了,别催了,这篇文章我一次性把 Shell 的内容说完

https://my.oschina.net/jiagoushi/blog/6037198 Shell 搜索与匹配 1、在文件中查找字符串 grep 命令可以搜索文件,查找指定的字符串。 $ grep myvar *.c 在这个例子中,我们搜索的文件全都位于当前目录下。因此,我们只使用了简单的 sh

[转帖]别让运维太忙,一文详解 Ansible 的自动化运维

https://zhuanlan.zhihu.com/p/270655214 一、Ansible 概述 Ansible 是近年来越来越火的一款开源运维自动化工具,通过Ansible可以实现运维自动化,提高运维工程师的工作效率,减少人为失误。 Ansible 通过本身集成的非常丰富的模块可以实现各种管

[转帖] 时区的坑,别再踩了!

https://www.cnblogs.com/codelogs/p/16027236.html 原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介# 最近在使用date命令时,发现表示东8区(中国时区)要使用GMT-8,但在Java中却需要使用GMT+8,如下:

[转帖]oracle中Rman增量备份下各级别level的区别

RMAN备份分为全备和增量备份两部分 增量备份:分为0 1 2级 ORACLE官方解释: A level 1 incremental backup can be either of the following types: Adifferential backup, which backs up a

[转帖]檢視硬體資源

https://benjr.tw/52888 在 Linux 系統可以透過 lshw 以及 lspci 看系統資訊,但這兩個執行檔的差別是什麼呢?? 完整系統硬體資訊 #lshw (list Hardware) – https://benjr.tw/53000透過 lshw 的功能可以檢視系統的硬體

[转帖]SSL 配置优化的若干建议

转载自本人博客:https://dev.tail0r.com/ssl-optimization/ 如果你配置SSL只是为了网站的网址前有一把锁的标志,那不如直接送你把锁好了。 别想了,这句话不是哪个安全专家说的,是我说的(逃) 今天写一篇文章记录一下自己 SSL 的配置优化过程。以下设置均为 Ngi

[转帖]diskspd的使用

https://www.cnblogs.com/tcicy/p/10005374.html 参数翻译 可测试目标: file_path 文件abc.file # #1为第一块物理磁盘[谨慎,别拿系统盘测试,一般用于准备投入的数据磁盘测试]

[转帖]国产CPU的选择

作者:guee链接:https://www.zhihu.com/question/564984900/answer/2751672897来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 CPU的选择为什么没有考虑龙芯3A5000呢?即使不考虑龙芯,也别买兆芯,海光CPU

[转帖]Redis-6.2.x版本官方发行说明(附谷歌翻译)【持续更新】

https://www.yii666.com/blog/12891.html 一、前言 本文只是单纯地翻译Redis官方的6.2.x版本的发行说明,不会对发行说明内容做任何改动,读者如果觉得有异议,可自行去Redis官网相关网页查阅。翻译工具翻译出来的不一定百分百准确,英语好的人别喷,大家都是英语差

[转帖]项目管理十大领域五大过程组

https://www.cnblogs.com/fan-yuan/p/11139010.html 十大领域:进度、成本、质量、范围等4个核心领域,风险、沟通、采购、人力资源、干系人等5个辅助领域,1个整体领域。 整体管理就是啥活儿都管点 范围管理就是知道自己在啥时候该干点啥 时间管理就是让你别心急,