2

我正在使用脚本使用命令获取文件的最后 n-2 行,然后使用 echo 将这些行打印到文件中。

last_n2_lines=`tail -n+3 $file`
echo "$last_n2_lines" >> $file

这里的这个回显从文件末尾删除了一个尾随的新行。供参考

尾 -n+3 文件 > file.new

运行良好。

4

2 回答 2

3

来自手册: http ://www.gnu.org/software/bash/manual/bashref.html#Command-Substitution

3.5.4 命令替换

命令替换允许命令的输出替换命令本身。当命令包含如下时,会发生命令替换:

$(command)

或者

`command`

Bash 通过执行命令并将命令替换替换为命令的标准输出来执行扩展,并删除任何尾随的换行符。嵌入的换行符不会被删除,但它们可能会在分词过程中被删除。命令替换 $(cat file) 可以替换为等效但更快的 $(< file)。

当使用旧式反引号形式的替换时,反斜杠保留其字面含义,除非后面跟着“$”、“`”或“\”。前面没有反斜杠的第一个反引号终止命令替换。使用 $(command) 形式时,括号之间的所有字符组成命令;没有人受到特殊对待。

命令替换可能是嵌套的。要在使用反引号形式时嵌套,请使用反斜杠转义内部反引号。

如果替换出现在双引号中,则不会对结果执行分词和文件名扩展。

强调我的。所以这不是一个错误。这是一个特点。

于 2013-02-10T09:39:03.580 回答
2

您可以通过使用来保存尾随的空行readarray来保存数据和printf输出。

就像是:

readarray last_n2_lines < <(tail -n+3 $file)
printf "%s" "${last_n2_lines[@]}" > ${file}.new

演示:

$ cat test; echo end 
1
2
3
4


end
$ tail -n+3 test ; echo end
3
4


end
$ readarray data < <(tail -n+3 test)
$ printf "%s" "${data[@]}" ; echo end  
3
4


end

解释:

  • readarray data将标准输入中的行读入名为data.
  • cmd1 < <(cmd2 param1 param2 ...)将 的输出重定向cmd2 param1 param2 ...到标准输入 if cmd1。小心语法:它必须是< [space] <(...), 之间没有空格 , 两者之间<(需要空格< <

所以在第一行之后,data包含所有tail -n+3输出的行。数组中的每一项都是包含行终止符的输入行。
以下是访问每个元素的方法。请注意,为数组中定义的每个项目打印两行:数组中的一行(包含换行符),以及由添加的换行符echo

$ echo "${data[0]}"
3

$ echo "${data[1]}"
4

$ echo "${data[2]}"


$ echo "${data[3]}"


$ echo "${data[4]}"  # out of bounds

$ 
  • ${data[@]}扩展到数组的所有元素data
  • printf "%s" param1 param2 ...打印其所有参数不变(即不添加或删除行终止符)。

所以第二条语句打印回读入的所有内容,保持不变。

于 2013-02-10T10:05:10.360 回答