如何在最后一个配置行后插入文本?

l0b*_*0b0 5 text-processing replace

我必须自动在配置文件中插入一行,但需要注意的是,如果页脚存在,它应该插入多行页脚注释和任何前面的空行或纯空白行之前。也就是说,应该在最后一个配置行之后立即插入新行,从而与原始文件形成单行差异。在伪代码中:

  1. 转到文件末尾。
  2. 返回到第一行(即文件中的最后一行)配置行(即非空行、仅包含空格、仅注释或空格后跟注释的行)。
  3. 在当前行后插入文本。

配置行的扩展正则表达式: ^\s*[^[:space:]#]

任何常见的 *nix 工具,例如sed, awk,edex都应该可以工作。


可能的解决方案及其问题:

  • 使用tac两次使其成为向前搜索问题而不是向后搜索问题。这意味着我必须将结果存储在一个临时文件中,然后替换原始文件,而不是在单个命令中执行此操作。
  • 使用sed -i逆转伎俩。这意味着将整个文件存储在内存中。
  • ex -c '1' -c '?^\s*[^[:space:]#]?' -c $'a\nmy new line\n.' -c 'wq' /path,我也了解将完整文件存储在内存中。

有没有解决这两个问题的解决方案?

示例起始文件:

# Universe configuration
#

pi = 3 # A good #
e = mc**2 # To within a hair

[cut 200 trillion lines]

# 
# END
#
Run Code Online (Sandbox Code Playgroud)

示例输入:

sol { mass = 42, start = 9.2 }
Run Code Online (Sandbox Code Playgroud)

预期输出:

# Universe configuration
#

pi = 3 # A good #
e = mc**2 # To within a hair

[cut 200 trillion lines]
sol { mass = 42, start = 9.2 }

# 
# END
#
Run Code Online (Sandbox Code Playgroud)

基于@StephaneChazelas 解决方案的通用函数

Sté*_*las 2

你可以按照这些思路做一些事情:

file=/some/file
newtext='sol { mass = 42, start = 9.2 }'
tac -- "$file" | 
  NEWTEXT=$newtext awk -v size="$(wc -c < "$file")" '
    $1 ~ /^[^#]/ {
      system("dd bs=1 seek=" size - length(footer) " conv=notrunc if=/dev/null")
      printf "%s\n%s", ENVIRON["NEWTEXT"], footer
      exit
    }
    {footer=$0 "\n" footer}' 1<> "$file"
Run Code Online (Sandbox Code Playgroud)

这会就地覆盖文件并仅将页脚存储在内存中。它需要非标准的 GNUtac命令。该文件必须是常规文本文件。