[英]How to write to first n lines of file in bash
I have a file test.txt
with following content我有一个包含以下内容的文件
test.txt
first
second
AAA
BBB
CCC
DDD
And I want to remove the first two lines and add new values to the first two lines,我想删除前两行并在前两行添加新值,
so,所以,
once the first two lines are removed, file should look like this:删除前两行后,文件应如下所示:
AAA
BBB
CCC
DDD
And then should add the two values to first line and then the second line, so the file would finally look like below:然后应该将这两个值添加到第一行,然后是第二行,因此文件最终如下所示:
new value at line 1
new value at line 2
AAA
BBB
CCC
DDD
So I tried the below command, but how can I remove the first two lines?所以我尝试了以下命令,但是如何删除前两行?
SERVER_HOSTNAME=$(hostname)
SERVER_IP=$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p')
sed -i "1s/.*/$SERVER_HOSTNAME/" /tmp/test.txt
sed -i "2s/.*/$SERVER_IP/" /tmp/test.txt
My problem is, when I first remove the first two lines, and execute the above command, it will replace the line number 1 and two with new values, but I want to add them on the top so the others (already existing content will shift down) will go down.我的问题是,当我首先删除前两行并执行上述命令时,它将用新值替换第 1 行和第 2 行,但我想将它们添加到顶部以便其他(已经存在的内容会移动下)将 go 下。
Could you please try following, written and tested with shown samples in GNU awk
.您能否尝试使用 GNU
awk
中的示例进行跟踪、编写和测试。 This will edit 1st and 2nd lines with shell variable values and do an inplace save into Input_file itself.这将使用 shell 变量值编辑第一行和第二行,并将就地保存到 Input_file 本身。
In case you want to keep 1st line's content as well as print current content then one could remove next
in FNR==2
OR FNR==1
conditions.如果您想保留第一行的内容并打印当前内容,则可以在
FNR==2
或FNR==1
条件下删除next
。
SERVER_HOSTNAME=$(hostname)
SERVER_IP=$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p')
awk -v server_ip="$SERVER_IP" -v server_hostname="$SERVER_HOSTNAME" '
FNR==1{ print server_hostname; next}
FNR==2{ print server_ip; ; next}
1
' Input_file > temp && mv temp Input_file
Explanation for above solution:上述解决方案的说明:
awk -v server_ip="$SERVER_IP" -v server_hostname="$SERVER_HOSTNAME" '
##Starting awk program from here, creating server_ip and server_hostname vars with respective shell vars.
FNR==1{ print server_hostname; next}
##Checking condition if this is 1st line then print server_hostname.
FNR==2{ print server_ip; ; next}
##Checking condition if this is 2nd line then print server_ip here.
1
##1 will print current line.
' Input_file
##Mentioning Input_file name here.
Don't run sed -i
repeatedly.不要重复运行
sed -i
。 Instead, combine all your commands into one script.相反,将所有命令组合到一个脚本中。
sed -i "1s/.*/$(hostname)/
2s/.*/$(ip -o route get to 8.8.8.8)/
2s/.*src \([0-9.]\+\).*/\1/" /tmp/test.txt
This is rather brittle, though;不过,这相当脆弱。 in particular, it will break if either of the command substitutions produces a slash in their output.
特别是,如果任一命令替换在其 output 中产生斜线,它将中断。
(IIRC ip
has options to produce machine-readable output; you should probably look into that instead of replacing out the parts you don't want.) (IIRC
ip
具有生成机器可读 output 的选项;您可能应该研究一下,而不是更换您不想要的部件。)
If you want to add, then delete, the sed
d
and a
commands do that, respectively.如果要添加然后删除
sed
d
和命令,则分别执行a
操作。 But removing two and adding two is obviously equivalent to replacing two.但是去掉二加二显然就等于换了二。
sed -i "1d
1a\hello
2d
2a\hello" file
Unfortunately, the a
command is poorly standardized, and it's unclear how two s
commands would not work, so I'm leaving this as a sketch.不幸的是,
a
命令的标准化很差,并且不清楚两个s
命令如何不起作用,所以我将其保留为草图。
Your existing sed
already does what you want;您现有的
sed
已经可以满足您的需求; it doesn't need you to remove the first two lines yourself first.它不需要您自己先删除前两行。
$ cat tmp.txt
first
second
AAA
BBB
CCC
DDD
$ SERVER_HOSTNAME=example.local
$ SERVER_IP=127.0.0.1
$ sed -i "1s/.*/$SERVER_HOSTNAME/;2s/.*/$SERVER_IP/" tmp.txt
$ cat tmp.txt
example.local
127.0.0.1
AAA
BBB
CCC
DDD
You may use this gnu sed
:您可以使用这个
gnu sed
:
gsed -i -e "1i\\$SERVER_HOSTNAME\n$SERVER_IP" -e '1,2{d;q;}' /tmp/test.txt
Or using POSIX sed:或使用 POSIX sed:
sed -i.bak "1,2{d;q;};3i\\
$SERVER_HOSTNAME
3i\\
$SERVER_IP
" /tmp/test.txt
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.