首页 > Linux技术 > here document 的一些技巧

here document 的一些技巧

2006年9月17日 wgzhao 发表评论 阅读评论

here document 就是一段特殊目的的代码块. 他使用I/O 重定向的形式来将一个命令序列传递到一个交互程序或者命令中, 比如ftp, cat, 或者ex 文本编辑器.
1 COMMAND < 2 ...
3 InputComesFromHERE

limit string 用来划定命令序列的范围(译者注: 两个相同的limit string 之间就是命令序列) .
特殊符号 << 用来表识limit string. 这个符号具有重定向文件的输出到程序或命令的输入的作用.

与 interactive-program < command-file 很相象, command-file 包含:

1 command #1
2 command #2
3 …

而here document 的形式看上去是如下的样子:
1 #!/bin/bash
2 interactive-program < 3 command #1
4 command #2
5 ...
6 LimitString

选择一个名字非常诡异的limit string 将会避免命令列表和limit string 重名的问题.
即使是某些不大可能的工具, 如vi 也可以使用here document.
1)使用vi创建一个文件,并写入内容
#cat fakevi.sh
#!/bin/bash

# 用非交互的方式来使用'vi'编辑一个文件.
# 模仿'sed'.

E_BADARGS=65

if [ -z “$1″ ]
then
echo “Usage: `basename $0` filename”
exit $E_BADARGS
fi

TARGETFILE=$1

# 在文件中插入两行, 然后保存.
#——–Begin here document———–#
/bin/vi $TARGETFILE < i
This is line 1 of the example file.
This is line 2 of the example file.

ZZ
x23LimitStringx23
#----------End here document-----------#

# 注意上边^[是一个转义符,键入Ctrl+v 就行,
#+ 事实上它是键.

# Bram Moolenaar 指出这种方法不能正常地用在'vim'上, ( Bram Moolenaar 是vim 作者),
#+ 因此这里使用了/bin/vi而不是vim,直接输入vi,调用的可能是vim,可以看看你的alias列表中是#+否 有vi的定义
exit 0

[root@lancy bin]# ./fakevi.sh one
Vim: Warning: Input is not from a terminal
[root@lancy bin]# cat one

This is line 1 of the example file.
This is line 2 of the example file.

2)多行消息输出
使用echo来打印单行消息非常有用,但是在打印消息块的时候就麻烦了一点,这个时候我们可以使用cat here document的的方式来解决
#!/bin/bash
cat < this is line 1
this is line 2
this is line 3
EndMsg
exit 0

这样可以打印上面的三行信息,用tab键退后是为了代码好看,但是带来的影响是tab键也将被输出,这可能不是我们所期望的,我们可以使用-here document 来解决,看看下面的例子
#!/bin/bash
cat <<-EndMsg
this is line 1
this is line 2
this is line 3
EndMsg
exit 0

看看打印的结果有什么不同?
3)参数替换
here document 支持参数和命令替换. 所以也可以给here document 的消息体传递不同的参数,
这样相应的也会修改输出.
看下面的代码
#!/bin/bash
NAME=${1:-”Mr. smith”}
cat < hello,there,$NAME
Greetings to you,$NAME
#this comment shows up in the output
EndMsg
exit 0

4)禁止参数替换
在here document 的开头引用或转义”limit string”会使得here document 的消息体中的参数替
换被禁用.这在需要某些原始输出时很有用。
再看下面的代码,看看输出和上面的有什么不同
#!/bin/bash
NAME=${1:-”Mr. smith”}
cat <<'EndMsg'
hello,there,$NAME
Greetings to you,$NAME
#this comment shows up in the output
EndMsg
exit 0

下面的两种情况类似
cat <<"EndMsg"
cat <<\EndMsg

禁用了参数替换后, 将允许输出文本本身. 产生脚本甚至是程序 代码就是这种用法的用途之一.

5)here document与函数
同一脚本中的函数也可以接受here document 的输出作为自身的参数.看下面的代码
#!/bin/bash
printsomething()
{
read one
read two
read three
echo “the value arg 1 is $one”
}
#上面这个函数无疑是一个交互性的函数,但是我们可以做调用
printsomething < this is one
this is two
this is three
EndMsg
exit 0

5)匿名 here document
做一个假命令来从一个here document 中接收输出. 这么做事实上就是创建了
一个”匿名”的here document.
看看下面的代码
#!/bin/bash
: < ${hostname?}${user?}${MAIL?} # 如果其中一个变量没被设置, 那么就打印错误信息.
TESTVARIABLES
exit 0

上边的这种技术当然也可以用来注释掉一段正在使用的代码, 如果你有某些特定调试要求的话
这将比对每行都敲入”#”来得方便的多, 而且如果你想恢复的话, 还得将添加上的”#”删除掉.
看下面的代码
#!/bin/bash
: < for i in *
do
cat $i
done
DebugIt
exit 0

这样这段for循环代码就注释了,下次要使用,只需要删除:<关于这种小技巧的另一个应用就是能够产生自文档化(self-documenting)的脚本.
#!/bin/bash
# self-document.sh: 自文档化(self-documenting)的脚本
# Modification of “colm.sh”.

DOC_REQUEST=70

if [ “$1″ = “-h” -o “$1″ = “–help” ] # 请求帮助.
then
echo; echo “Usage: $0 [directory-name]”; echo
sed –silent -e '/DOCUMENTATIONXX$/,/^DOCUMENTATIONXX$/p' “$0″ |
sed -e '/DOCUMENTATIONXX$/d'; exit $DOC_REQUEST; fi

: < List the statistics of a specified directory in tabular format.
---------------------------------------------------------------
The command line parameter gives the directory to be listed.
If no directory specified or directory specified cannot be read,
then list the current working directory.

DOCUMENTATIONXX

if [ -z "$1" -o ! -r "$1" ]
then
directory=.
else
directory="$1"
fi

echo "Listing of "$directory":"; echo
(printf "PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAME\n" \
; ls -l "$directory" | sed 1d) | column -t

exit 0

注意: Here document 创建临时文件, 但是这些文件将在打开后被删除, 并且不能够被任何其
他进程所存取.
[root@lancy bin]# bash -c 'lsof -a -p $$ -d0' < >EOF
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
lsof 6238 root 0r REG 3,5 0 212880 /tmp/sh-thd-1158429626 (deleted)

警告: 结束的limit string, 就是here document 最后一行的limit string, 必须开始于第一
个字符位置. 它的前面不能够有任何前置的空白. 而在这个limit string 后边的空白也会
引起异常问题. 空白将会阻止limit string 的识别.
(以上部分内容来自ABS一书)

原创文章,转载请注明: 转载自Linux|系统管理|WEB开发

本文链接地址: here document 的一些技巧

分类: Linux技术 标签: ,
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.