shell其他

懒人的小窝 2020-07-04

一.输入重定向

和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:

command < file

这样,本来需要从键盘获取输入的命令会转移到文件读取内容。

注意:输出重定向是大于号(>),输入重定向是小于号(<)。

例如,计算 users 文件中的行数,可以使用下面的命令:

wc -l users
2 users
  也可以将输入重定向到 users 文件:


wc -l < users
2

注意:上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。

重定向深入讲解

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。

如果希望 stderr 重定向到 file,可以这样写:

command 2 > file

如果希望 stderr 追加到 file 文件末尾,可以这样写:

command 2 >> file

2 表示标准错误文件(stderr)。

如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:

command > file 2>&1

如果希望对 stdin 和 stdout 都重定向,可以这样写:

command < file1 >file2

command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。

全部可用的重定向命令列表:

命令    说明
command > file    将输出重定向到 file。
command < file    将输入重定向到 file。
command >> file    将输出以追加的方式重定向到 file。
n > file    将文件描述符为 n 的文件重定向到 file。
n >> file    将文件描述符为 n 的文件以追加的方式重定向到 file。
n >& m    将输出文件 m 和 n 合并。
n <& m    将输入文件 m 和 n 合并。
<< tag    将开始标记 tag 和结束标记 tag 之间的内容作为输入。

二./dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:

command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到禁止输出的效果。

如果希望屏蔽 stdout 和 stderr,可以这样写:

command > /dev/null 2>&1

这样不会在屏幕打印任何信息。

三.Shell文件包含

像其他语言一样,Shell 也可以包含外部脚本,将外部脚本的内容合并到当前脚本。

Shell 中包含脚本可以使用 . filename 或 source filename 。

两种方式的效果相同,简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格。

示例: 被包含文件:sub.sh

name="yjc"

主文件:test.sh

. ./sub.sh
echo $name

运行结果:

yjc

四.获取当前正在执行脚本的绝对路径

正确的命令是:

basepath=$(cd `dirname $0`; pwd)
  直接使用pwd或者dirname $0是不对的。


五.按特定字符串截取字符串
  示例:截取/www/html/php/myapp/里的myapp。
  方案:

str=/www/html/php/myapp/
b=($(echo $str|sed ‘s#/# #g‘))
b_len=`expr ${#b[*]} - 1`
app_name=${b[$b_len]}
echo $app_name

这里利用sed将字符串按指定字符截成数组,然后取最后一个。

计算数组长度:${#arr[*]}
  计算则需要使用expr命令

六.awk

  awk简介

awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件(或其他方式的输入流, 如重定向输入)逐行的读入(看作一个记录集), 把每一行看作一条记录,以空格(或\t,或用户自己指定的分隔符)为默认分隔符将每行切片(类似字段),切开的部分再进行各种分析处理。

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

Awk基本语法: 

awk ‘pattern1 {command1;command 2…; command 3}  pattern2 { command …}‘

pattern表示用来过滤记录的模式,可是是正则表达式,关系运算表达式,也可以什么也没有(表示选中所有记录)。

每个pattern选中的行记录会被花括号括起来的命令command操作一遍, command之间用;分割。 花括号里面可以什么也没有, 则默认为print输出整行记录。 Comamnd可以是输出, 可以是算术运算,逻辑运算,循环控制等等。

  示例

s.txt

zhangsan 1977 male computer 83
lisi 1989 male math 99
wanglijiang 1990 female chinese 78
xuliang 1977 male economic 89
xuxin 1986 female english 99
wangxuebing 1978 male math 89
lichang 1989 male math 99
wanglijiang 1990 female chinese 78
zhangsansan 1977 male computer 83 
langxuebing 1978 male math 89
lisibao 1989 male math 99
xiaobao 1990 female chinese 78

一行中的5个字段分别表示姓名, 出生年, 性别,科目,分数, 是一个很传统很典型的报表文件。

现在演示awk是如何查找的:

1)直接输出1990年出生的同学:

$ awk ‘/1990/‘ s.txt

wanglijiang 1990 female chinese 78
wanglijiang 1990 female chinese 78
xiaobao 1990 female chinese 78

或者:

$ awk ‘/1990/{print $0}‘ s.txt

awk默认把输入的内容以空格拆分出每列。$0表示匹配所有列,print $0将输出所有列,每列分隔符是空格。

2)对chinese的课程的行输出"语文":

$ awk ‘/chinese/{print "语文"}‘ s.txt

  语文
  语文
  语文

3)记录的头部和结尾加上一段说明:

$ awk ‘BEGIN{print "Result of the quiz:\n"}{print $0}END{print "------"}‘ s.txt
Result of the quiz:

zhangsan 1977 male computer 83
lisi 1989 male math 99
wanglijiang 1990 female chinese 78
xuliang 1977 male economic 89
xuxin 1986 female english 99
wangxuebing 1978 male math 89
lichang 1989 male math 99
wanglijiang 1990 female chinese 78
zhangsansan 1977 male computer 83
langxuebing 1978 male math 89
lisibao 1989 male math 99
xiaobao 1990 female chinese 78
------

AWK工作流程:逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行用户想要到的操作。

BEGIN只会在最开始执行;END只会在扫描所有行数之后执行。BEGIN和END之间的花括号的内容每扫描一行都会执行。

 4)查找女生的成绩且只输出姓名、学科、成绩:

$ awk ‘$3=="female"{print $1,$4,$5}‘ s.txt

wanglijiang chinese 78
xuxin english 99
wanglijiang chinese 78
xiaobao chinese 78

  $1表示第1列,$n类推。这里条件是表达式,而不是正则。print里,表示空格分隔符。

  5)找出1990年出生的学生姓名,并要求匹配正则:

$ awk ‘$2~/1990/{print $1}‘ s.txt
wanglijiang
wanglijiang
xiaobao

这里~表示匹配正则表达式。!~表示不匹配正则表达式。

如果需要多选,则改成:

$ awk ‘$2~/(1990|1991)/{print $1}‘ s.txt

awk更多内容详见:https://www.cnblogs.com/52fhy/p/5836429.html#autoid-3-4-0

 

相关推荐