英文:
AWK insert line at top of a file
问题
我想在这里做一些解释!
我对awk不太了解,我想知道如何在文件顶部插入一行。
到目前为止,这是我尝试过的内容:
file.txt
内容行
另一行
awk命令
awk 'BEGIN {print "第一行" } {print}' file.txt
输出
第一行
内容行
另一行
然而,当使用-i inplace
运行时,不会写入文件,只会给我这个输出
第一行
我想知道我做错了什么,如果你们能解释一下,我会非常感激。
英文:
I would like to get some explanation here!
I'm new to awk and I'd like to know how do I insert a line at to of a file
.
This is what I've tried so far
file.txt
content line
another line
awk command
awk 'BEGIN {print "first line" } {print}' file.txt
the output
first line
content line
another line
however, when run with -i inplace
doesn't write to the file only gives me this output
first line
I would like to know what I am doing wrong and if you guys can explain it I'd really appreciate.
答案1
得分: 2
BEGIN{}
块在处理任何文件之前被处理,这意味着由 BEGIN{}
块生成的任何输出都只能发送到标准输出。
要将这行插入文件中,您需要将 print "first line"
移动到脚本的主体部分,以便它可以与文件一起处理。
基于在读取输入文件的第一行时插入新行的想法:
awk -i inplace 'FNR==1 {print "first line;"}1' file.txt
cat file.txt
first line
content line
another line
注意:
- 如果您将多个文件提供给
awk
,FNR==1
将适用于每个文件,否则如果只有一个输入文件,NR==1
也足够。 - 独立的
1
是非零的,因此被awk
视为“true”;在这里,它适用于所有输入行,对于“true”,默认行为是将输入行传递到标准输出(与{print}
效果相同)。
英文:
The BEGIN{}
block is processed before any files are processed which means any output generated by the BEGIN{}
block has nowhere to go but to stdout.
To get the line inserted into the file you need to move the print "first line"
into the main body of the script where it can be processed along with the file.
One idea based on inserting the new row while reading the first line of the input file:
$ awk -i inplace 'FNR==1 {print "first line"}1' file.txt
$ cat file.txt
first line
content line
another line
NOTES:
FNR==1
will apply to each file if you happen to feed multiple files toawk
, otherwiseNR==1
will also suffice if it's just the one input file- the stand-alone
1
is non-zero and thus considered byawk
as'true'
; here it applies against all input lines and the default behavior for a'true'
is to pass the input line through to stdout (effectively the same as{print}
)
答案2
得分: 2
-i inplace
选项包括内置的 inplace.awk
包含文件,以模拟 sed -i
的原地编辑,但这种模拟方法有一些注意事项。
因为它通过调整每个输入文件的处理方式(使用 BEGINFILE
模式)来工作,所以在 BEGIN
选择器中打印的任何内容仍然会输出到启动输出流,而不是到“调整后”的输出流。这是因为在那个时候第一个输入文件尚未开始处理。
所以你将看到 first line
输出到标准输出,然后从输入文件打印的两行被原地写回到该文件。你可能没有意识到最后一部分,因为在写回时没有更改文件中的行。
毫无疑问,这对于 inplace.awk
的创建者来说是一个困难的实现决策,因为需要为多个文件的原地编辑提供支持。问题是:在原地编辑中 BEGIN
中的输出应该放在哪里?
你有几个选项。
首先,如果你知道你只会处理一个文件,你可以使用常规的技巧,使用 BEGIN
但不使用 inplace
:
awk 'BEGIN {print "first line" } {print}' file.txt > /tmp/$$ && mv /tmp/$$ file.txt
其次,使用 inplace
但不使用 BEGIN
,你需要首先决定它应该影响哪个输入文件。如果你希望它影响所有输入文件,那就意味着类似于以下方式:
awk -i inplace 'FNR==1 {print "first line";print;next} {print}' file1.txt file2.txt
如果你只想影响第一个输入文件,使用 NR
而不是 FNR
(前者永不减少,后者对每个新的输入文件都重置为1)。
最后,对于所有文件都应该受影响的情况,你可以使用与 inplace
本身使用的相同方法。
由于特殊模式(如 BEGIN
)按照定义的顺序执行(而 -i
在你的脚本处理之前执行),所以只需使用 BEGINFILE
而不是 BEGIN
,如下所示:
=====
pax@styx:~$ cat xx.001
Original line from xx.001
=====
pax@styx:~$ cat xx.002
Original line from xx.002
=====
pax@styx:~$ cat xx.awk
BEGINFILE {
print "inserted line"
}
{
print
}
=====
pax@styx:~$ awk -i inplace -f xx.awk xx.001 xx.002
=====
pax@styx:~$ cat xx.001
inserted line
Original line from xx.001
=====
pax@styx:~$ cat xx.002
inserted line
Original line from xx.002
inplace
的 BEGINFILE
首先会执行其魔术以捕获输出(每个输入文件),然后你的 BEGINFILE
将在该捕获区域中打印。
英文:
The -i inplace
includes the built-in inplace.awk
include file to emulate sed -i
in-place editing but there are some caveats that come from the method used for this emulation.
Because it works by fiddling with the processing of each input file (by using the BEGINFILE
pattern), anything printed in the BEGIN
selector still goes to the start-up output stream rather than to the "fiddled" output stream. That's because the first input file has yet to begin processing at that point.
So what you'll see is first line
going to standard output then the two lines from the input file being printed in-place back to that file. You just may not have realised that last bit since you don't change the lines in the file when you write them back.
This was no doubt a difficult implementation decision for the creators of inplace.awk
since in-place editing over multiple files needs to be catered for. The question is: where should output go in BEGIN
for in-place editing?
You have a couple of options here.
First, if you know you'll only ever process one file, you can use the normal trick, with BEGIN
but without inplace
:
awk 'BEGIN {print "first line" } {print}' file.txt > /tmp/$$ && mv /tmp/$$ file.txt
Second, using inplace
but not BEGIN
, you need to first decide which of the input files it should affect. If you want it to affect all input files, that means something like:
awk -i inplace 'FNR==1 {print "first line";print;next} {print}' file1.txt file2.txt
If you want it to affect just the first input file, use NR
rather than FNR
(the former never decreases, the latter resets to one for each new input file).
Finally, for the case where all files should be affected, you can use the same method that inplace
itself uses.
As special patterns like BEGIN
are executed in order of definition (and -i
comes before processing of your script), simply use BEGINFILE
rather than BEGIN
, as per the following transcript:
=====
pax@styx:~$ cat xx.001
Original line from xx.001
=====
pax@styx:~$ cat xx.002
Original line from xx.002
=====
pax@styx:~$ cat xx.awk
BEGINFILE {
print "inserted line"
}
{
print
}
=====
pax@styx:~$ awk -i inplace -f xx.awk xx.001 xx.002
=====
pax@styx:~$ cat xx.001
inserted line
Original line from xx.001
=====
pax@styx:~$ cat xx.002
inserted line
Original line from xx.002
The BEGINFILE
from inplace
will first weave its magic to capture output (per input file), then your BEGINFILE
will print to that capture area.
答案3
得分: 0
$ awk -i inplace 'NR==1{print "第一行";print;next} {print}' file ; cat file
第一行
原始内容行 1
原始内容行 2
英文:
What I would do:
$ awk -i inplace 'NR==1{print "first line";print;next} {print}' file ; cat file
first line
original content line 1
original content line 2
答案4
得分: 0
非awk版本:
我很兴奋地看到-i inplace
选项,但在macOS和BSD上不可用。所以除了@paxdiablo的临时文件解决方案之外,以下是如何使用/bin/ed
在行前添加内容的方法。
ed -s file.txt << EOF
1i
first line
.
w
EOF
英文:
Non-awk version:
I was excited to see the -i inplace
option, but it's not available in macOS and BSDs. So in addition to @paxdiablo's solution of a tmp file, here's how you can prepend lines with /bin/ed
.
ed -s file.txt << EOF
1i
first line
.
w
EOF
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论