shell输出的传递

输出的传递

  shell脚本最棒的特性之一就是可以将多个命令组合起来生成输出

  一个命令的输出可以作为另一个命令的输入,而这个命令的输出又会传递至下一个命令,以此类推。

  这种命令组合的输出可以被存储在变量中。

1 管道

1.1 命令的组合

$ ls | cat -n > out.txt

  ls (列出当前目录内容)的输出被传给 cat -n ,后者为通过 stdin 所接收到的输入内容加上行号,然后将输出重定向到文件out.txt

2 子shell

  子shell一般有两种实现方式

  1. $()
  2. ``

2.1 利用子shell生成独立的进程

  子shell本身就是独立的进程。可以使用 () 操作符来定义一个子shell

$> pwd
$> (cd /bin; ls)
$> pwd

  当命令在子shell中执行时,不会对当前shell造成任何影响;所有的改变仅限于该子shell内。

2.2 引用子shell保留空格和换行符

  为了保留输出的空格和换行符( \n ),必须使用双引号

$ cat text.txt
1
2
3
$ out=$(cat text.txt)
$ echo $out
1 2 3       #丢失了换行符
$ out="$(cat text.txt)"
$ echo $out
1
2
3           #没有丢失换行符

2.2.1 依然不保留换行符的思考

  先用set | grep out 你会看到两个out是这样保存的:

out=$'1\n2\n3'

  $'...'表示里面反斜杠开头是转义字符,这种字符串也叫ANSI C like strings,和下面这个是有区别的:

  another='1\n2\n3'

  echo $'1\n2\n3' 就能得到你想要的结果。

  也就是说,变量里实际是有换行符的,只是传给echo的时候做了些变换。

  bash把变量展开之后,会根据IFS(Internal Field Separator)把输入划分成多个单独的单词(Word splitting),除了在双引号里,原输入里的IFS都换成空格,连续空格再缩成1个空格。默认的IFS里有空格、换行和Tab。

  所以输入echo $out,bash处理是这样的:

echo<空格>$out
--展开out-->
echo<空格>1<换行>2<换行>3
--根据IFS分词-->
echo<空格>1<空格>2<空格>3

  所以用1、2、3作为参数调用echo。

  这时候只要加上双引号阻止分词就可以了:

echo<空格>"$out"
--展开out-->
echo<空格>"1<换行>2<换行>3"
--根据IFS分词,双引号里不分词-->
echo<空格>"1<换行>2<换行>3"

  1<换行>2<换行>3 被当作参数传给echo,然后就是你想要的结果了。

  也可以把IFS设成其他字符,例如IFS=,,然后echo out和echo "out"的结果是一样的,因为输入里没有IFS,不会被分词。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。