I/O重定向

用于捕捉一个文件、命令、程序或脚本,甚至代码块的输出,
然后把捕捉到的输出作为输入发送给另一个文件、命令、程序或脚本。

管道

管道简介

管道技术是Linux一种基本的进程间通信技术,利用先进先出来指挥进程间通信。

管道可应用于应用程序之间、Linux命令之间,以及应用程序和Linux命令之间的通信。

1
2
3
command1 | command2 | command3 | ... | commandn
# command1的输出发送给command2,作为command2的输入,后面的命令依次类推。
# 如果没有管道,command1的输出结果直接显示在Shell上。
cat和more命令

cat和more命令用来显示文件的内容。

1
2
3
4
5
# 具体 option 查看帮助文档
cat [option] filename
more [option] [+linenum] filename # [+linenum] 指定显示文件的起始行

# cat命令不提供分页功能,more在显示超过一页的文件时提供了分页的功能。
1
2
# 将ls的结果分页展示
ls -l | more
sed命令与管道
1
2
sed [选项] 'sed命令' 输入文件  # 原始的sed命令
| sed [选项] 'sed命令' # sed命令与管道结合
1
2
# 打印ls -l结果的第1~5行
ls -l | sed -n '1,5p'
1
2
3
4
5
# 结合命令替换、管道、sed、变量赋值、echo等知识
variable1="abcdef"
replace="123"
variable2=`echo "$variable1" | sed "s/abc/$replace/g"`
echo "$variable2" # 123def

I/O重定向

I/O重定向:捕捉一个文件、命令、程序或脚本,甚至代码块的输出,
然后把捕捉到的输出作为输入发送给另一个文件、命令、程序或脚本。

  • 文件标识符(FD)

用文件标识符来标识一个进程正在访问的特定文件,当打开一个文件或者创建一个文件时,
Linux将返回一个文件标识符供其他操作引用。

当启动一个进程时,将自动为该进程打开三个文件:标准输入、标准输出和标准错误输出,分别用0,1,2标识。

  • tee命令

T型数据流,讲一个输出分为两个支流,一个到标准输出,一个到某个输出文件。

1
2
3
4
5
# 将who的结果保存到output文件
who | tee output

# 将who的结果追加到output文件
who | tee -a output
  • I/O重定向符号
1
2
3
4
5
6
7
8
9
10
cat > newfile  # 将键盘的输入重定向到newfile
# 在此输入内容
# 按CTRL+D结束输入

cat >> newfile # 将键盘的输入追加到newfile
# 在此输入内容
# 按CTRL+D结束输入

cat newfile
# 显示刚才编辑的内容
1
2
3
4
5
6
n> filename  # 将文件标识符为n的内容输出到filename中

# 将指定文件标识符的内容重定向到另一文件中
ls z-file # 假设:当前目录下没有z-file

ls z-file 2> newfile # 将错误信息输入到newfile中
1
2
3
4
< filename  #  将文件的内容读入(重定向)标准输入中
n< filename # 将文件的内容读入(重定向)文件标识符为n的文件中

wc -l < filename # 统计文件的行数
  • exec命令的用法

可以通过文件标识符打开或关闭文件,
也可以将文件重定向到标准输入或将标准输出重定向到文件

1
2
3
4
5
6
7
exec 8<&0  # 将FD 0(标准输入)复制到FD 8

exec < hfile # 将hfile重定向到标准输入
read a # 读取hfile的第一行
echo "$a"

exec 0<&8 8<&- # 将FD 8复制到FD 0(标准输入),关闭FD 8的输入(恢复标准输入)
1
2
3
4
5
6
exec 8>&1  # 将FD 1(标准输出)复制到FD 8

exec > log # 将标准输出重定向log文件
echo "asd" # 此时会将asd写入到log文件中

exec 1>&8 8>&- # 将FD 8复制到FD 1(标准输出),关闭FD 8的输出(恢复标准输出)
  • tty

待研究

1
sudo echo "asd" > /dev/tty1  # 重定向到tty1,在tty1会接收到asd
  • 代码块重定向

指在代码块内将标准输入标准输出重定向到文件,而在代码块之外保留默认状态。
可以重定向的代码块是while,until,for等循环结构,也可以是if/then测试结构,甚至可以是函数。

循环

1
2
3
4
5
# `标准输入`重定向到`文件`
done > filename

# `标准输出`重定向到`文件`
done < filename
1
2
3
4
5
6
7
8
ls /etc > log  # 将结果重定向到log中

while [ "$filename" != "rc.d" ]; do
read filename
let "count+=1"
done < log # 将标准输入重定向到log文件

echo "$count"

if/then

1
2
3
4
5
6
if [condition]
then
...
else
...
fi < filename
1
2
3
4
if [ -z "$1" ]
then
echo "is null" # 输出到log文件中
fi > log

命令行处理

具体参考:

shell对每一个命令都要经过命令行处理流程进行处理。如,变量替换、通配符展开等。

eval命令

eval命令将其参数作为命令行,让shell重新执行该命令。

  • 由于命令行处理需要步骤,所以当在后面替换的时候出现了前面已经处理过的情况,
    执行命令时会发生错误,所以用eval表明处理后的命令还需要重新处理一遍再执行。

  • 如果命令中包含变量替换,且变量中包含任何需要shell在命令中直接看到的字符
    就需要使用eval命令,如命令结束符(;,|,&)、I/O重定向符(<,>)和引号等。

1
2
3
pipe="|"
ls $pipe wc -l # 会报错(因为“管道符”需要在第一步被发现)
eval ls $pipe wc -l # 正常执行