假设我有一个direction
包含以下行的文件
east
north
south
west
south-west
并使用循环并echo
在 shell 脚本中生成以下输出:
Direction: east
Direction: north
Direction: south
Direction: west
Last direction: south-west
换句话说,我想对脚本中的最后一行做一些不同的事情。
答案1
bash
无法检测文件的结尾(不尝试读取下一行并失败),但 perl 可以使用其eof
功能:
$ perl -n -e 'print "Last " if eof; print "Direction: $_"' direction
Direction: east
Direction: north
Direction: south
Direction: west
Last Direction: south-west
注意:与echo
bash 不同,print
perl 中的语句不会打印换行符,除非您 1. 通过包含\n
在要打印的字符串中明确告诉它,或者 2. 使用 perl 的-l
命令行选项,或者 3. if字符串已经包含换行符......就像$_
- 的情况一样,这就是为什么你经常需要chomp()
它来删除换行符。
BTW,在 perl 中,$_
是当前输入行。或者任何未指定实际变量名称的循环中的默认迭代器(通常称为“当前事物”,可能是因为“dollarunderscore”有点拗口)。许多$_
如果未提供,perl 函数和运算符将用作默认/隐式参数。查看man perlvar
并搜索$_
.
sed
也可以 -$
地址与文件的最后一行匹配:
$ sed -e 's/^/Direction: /; $s/^/Last /' direction
Direction: east
Direction: north
Direction: south
Direction: west
Last Direction: south-west
规则的顺序sed
很重要。我的第一次尝试以错误的方式进行了(并打印了“方向:最后的西南方向”)。此 sed 脚本始终将“Direction:”添加到每行的开头。在最后一行 ( $
) 中,它将“Last ”添加到已被前一条语句修改的行的开头。
答案2
循环无法知道何时到达终点,除非它确实到达终点。因此,要么处理文件两次,一次获取行数,另一次输出,或者打印每次迭代时的前一个值和退出循环时的最后一个值:
prev=""
while read direction; do
if [ -n "$prev" ]; then
echo "Direction: $prev"
fi
prev="$direction"
done < direction
echo "Last Direction: $prev"
答案3
的一个变体FelixJN 的回答,将行读入数组,但使用 bash 内置函数而不是 bash 循环:
mapfile -t DIR < direction
printf "Direction: %s\n" "${DIR[@]::${#DIR[@]}-1}"
printf "Last direction: %s\n" "${DIR[-1]}"
地图文件是 Bash 4 中添加的内置函数,它将标准输入读取到数组中,每个条目一行。该-t
选项会去除换行符。
printf
将重复应用其格式字符串,直到用完所有输入参数。
答案4
您可以混合使用paste
,tail
和head
:
$ paste -s -d'\n' <(head -n -1 direction | sed 's/^/Direction: /') <(tail -n1 direction | sed 's/^/Last direction: /')
Direction: east
Direction: north
Direction: south
Direction: west
Last direction: south-west
paste -s -d'\n'
使用换行符作为分隔符-d'\n'
,并带有选项 和 选项-s
:-s, --serial
一次粘贴一个文件而不是并行粘贴head -n -1
检索除最后一行之外的所有行,然后通过管道传输到sed
仅在这些行中执行您需要的命令。tail -n1 file
检索文件的最后一行,然后通过管道传输到sed
仅执行该行中所需的命令。
或者更简洁地只是使用cat
而不是paste
,如所指出的@米克·马泰奥的评论:
$ cat <(head -n -1 direction | sed 's/^/Direction: /') <(tail -n1 direction | sed 's/^/Last direction: /')