将一个文件的内容复制到另一个文件中相对于文件末尾的位置

Copying the contents of a file into another file at a point relative to the end of the file

StackExchange 新手,如有错误请见谅。

我有一个输入文件需要复制到另一个文件中,在最后一个字符之前。

inputfile.txt:

input {
       "inputstuff"
}

filetowriteto.txt:

Stuff {
       foo {
            "foostuff"
       }
       bar {
            "barstuff"
       }
}

在 运行 脚本之后,生成的文件现在应该是:

filetowriteto.txt:

Stuff {
       foo {
            "foostuff"
       }
       bar {
            "barstuff"
       }
       input {
              "inputstuff"
       }
}

基本上,脚本会复制 input 行集并将它们粘贴到 filetowriteto.txt 中最后一个右括号之前。

脚本不能依赖行数,因为 filetowriteto.txt 没有可预测数量的 foo 或 bar 行,而且我不知道如何使用 sed 或 awk 来执行此操作。

尝试:

$ awk 'FNR==NR{ if (NR>1) print last; last=[=10=]; next} {print "       " [=10=]} END{print last}' filetowriteto.txt inputfile.txt 
Stuff {
       foo {
            "foostuff"
       }
       bar {
            "barstuff"
       }
       input {
              "inputstuff"
       }
}

要就地更改文件:

awk 'FNR==NR{ if (NR>1) print last; last=[=11=]; next} {print "       " [=11=]} END{print last}' filetowriteto.txt inputfile.txt >tmp && mv tmp filetowriteto.txt

工作原理

  • FNR==NR{ if (NR>1) print last; last=[=12=]; next}

    在读取第一个文件时,(a)如果我们不在第一行,打印last的值,(b)将当前行的文本分配给last,和 (c) 跳过其余命令并跳转到 next 行。

    这使用了常见的 awk 技巧。条件 FNR==NR 仅在我们读取第一个文件时为真。这是因为,在 awk 中,NR 是我们到目前为止已经读取的行数,而 FNR 是我们到目前为止从当前文件读取的行数。因此,FNR==NR 仅在我们从第一个文件读取时为真。

  • print " " [=18=]

    在读取第二个文件时,打印每一行,并在前面加上一些白色 space。

  • END{print last}

    我们打印完第二个文件后,打印第一个文件的最后一行。

鉴于:

$ cat /tmp/f1.txt
input {
       "inputstuff"
}
$ cat /tmp/f2.txt
Stuff {
       foo {
            "foostuff"
       }
       bar {
            "barstuff"
       }
}

您可以使用 command grouping 来实现:

$ ( sed '$d' f2.txt ; cat f1.txt ; tail -n1 f2.txt ) 

或(此版本不创建子shell)

$ { sed '$d' f2.txt ; cat f1.txt ; tail -n1 f2.txt; } 

它是如何工作的?

  1. sed '$d' f2.txt 打印除 f2.txt

  2. 最后一行以外的所有内容
  3. cat f1.txt 在那个点打印 f1.txt

  4. tail -n1 f2.txt 现在打印 f2 的最后一行

如果要缩进 f1.txt,请使用 sed 而不是 cat。您还可以使用 sed 打印最后一行:

$ { sed '$d' /tmp/f2.txt ; sed 's/^/       /' /tmp/f1.txt ; sed -n '$p' /tmp/f2.txt;  } 
Stuff {
       foo {
            "foostuff"
       }
       bar {
            "barstuff"
       }
       input {
              "inputstuff"
       }
}

然后,如果您希望使用 > 重定向,您可以将分组的输出重定向到一个文件。

$ cat tst.awk
NR==FNR {
    rec = (NR>1 ? rec ORS : "") [=10=]
    next
}
FNR>1 {
    print prev
    if ( sub(/[^[:space:]].*/,"",prev) ) {
        indent = prev
    }
}
{ prev=[=10=] }
END {
    gsub(ORS,ORS indent,rec)
    print indent rec ORS prev
}

$ awk -f tst.awk inputfile.txt filetowriteto.txt
Stuff {
       foo {
            "foostuff"
       }
       bar {
            "barstuff"
       }
       input {
              "inputstuff"
       }
}

上面使用要修改的文件的最后一行之前的最后一个非空行的缩进来设置它插入的新文件的缩进。